alchemylab 2.3.0 → 3.0.1
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/README.md +0 -1
- package/dist/24.js +3 -1
- package/dist/414.js +43 -17
- package/dist/478.js +13 -53
- package/dist/579.js +13 -9
- package/dist/60.js +10 -10
- package/dist/776.js +30 -22
- package/dist/9.js +26 -0
- package/dist/902.js +26 -0
- package/dist/912.js +30 -16
- package/dist/994.js +84 -83
- package/dist/cli.js +5402 -3095
- package/dist/document-textconv.js +174 -115
- package/dist/http-server.js +2934 -2195
- package/dist/index.js +2985 -2246
- package/dist/mcp-direct.js +2910 -2131
- package/dist/plugins/hooks/plugin.js +1 -1
- package/package.json +13 -21
package/README.md
CHANGED
|
@@ -29,7 +29,6 @@ Open the project at https://alchemylabcode.com and say what you want in plain wo
|
|
|
29
29
|
|
|
30
30
|
```
|
|
31
31
|
alchemy start the local server and the agent console (default)
|
|
32
|
-
alchemy serve start the local server only
|
|
33
32
|
alchemy logout forget the stored login
|
|
34
33
|
alchemy --help
|
|
35
34
|
```
|
package/dist/24.js
CHANGED
|
@@ -34,4 +34,6 @@ const s=e.find(t=>"pending"===t.state||"running"===t.state),n=e.filter(t=>"compl
|
|
|
34
34
|
return{current:s?.name??null,recent:n.map(t=>t.name),lastActivityTime:o}},exports.formatTimeSince=s,exports.deriveActivityStatus=function(t,e){const n=t||e,o=Date.now()-n
|
|
35
35
|
if(t&&o<6e4)return{status:"working",detail:`last action ${s(o)}`,isReady:!1}
|
|
36
36
|
const i=s(o).replace(/ ago$/,"")
|
|
37
|
-
return o>3e5&&t?{status:"stalled",detail:`no activity for ${i}`,isReady:!0}:t?{status:"idle",detail:`no activity for ${i}`,isReady:!0}:{status:"idle",detail:"no tool activity",isReady:!0}},e(59860),e(15899),e(47617),e(39844),e(6688),e(87280),e(58824),e(79896),e(16928),e(8955),e(82272),process.env.ALCHEMY_DEBUG_LOGS
|
|
37
|
+
return o>3e5&&t?{status:"stalled",detail:`no activity for ${i}`,isReady:!0}:t?{status:"idle",detail:`no activity for ${i}`,isReady:!0}:{status:"idle",detail:"no tool activity",isReady:!0}},e(59860),e(15899),e(47617),e(39844),e(6688),e(87280),e(58824),e(79896),e(16928),e(8955),e(82272),process.env.ALCHEMY_DEBUG_LOGS
|
|
38
|
+
const n=e(79414)
|
|
39
|
+
e(52232),(0,n.getActionServerPort)(),new Map}}
|
package/dist/414.js
CHANGED
|
@@ -1,18 +1,44 @@
|
|
|
1
1
|
"use strict"
|
|
2
|
-
exports.ids=[414],exports.modules={79414(
|
|
3
|
-
if(
|
|
4
|
-
const o=(0,u.join)(
|
|
5
|
-
if((0,i.existsSync)(o))try{const
|
|
6
|
-
if("number"==typeof
|
|
7
|
-
if(!
|
|
8
|
-
const
|
|
9
|
-
return"string"==typeof
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
const
|
|
16
|
-
|
|
17
|
-
const f=
|
|
18
|
-
let
|
|
2
|
+
exports.ids=[414],exports.modules={79414(e,exports,t){function r(){return process.env.ALCHEMY_PROJECT_PATH||process.cwd()}function n(e){const t=Date.now(),n=!e
|
|
3
|
+
if(n&&null!==d&&t-p<5e3)return d
|
|
4
|
+
const o=(0,u.join)(e||r(),".alchemy_lab","action-server.json")
|
|
5
|
+
if((0,i.existsSync)(o))try{const e=(0,i.readFileSync)(o,"utf-8"),r=JSON.parse(e)
|
|
6
|
+
if("number"==typeof r.port&&r.port>0&&r.port<65536)return n&&(d=r.port,p=t),r.port}catch{}return n&&(d=3456,p=t),3456}function o(e){return e||r()}async function c(e,t){try{const n=(0,h.localSecretForUrl)(`http://localhost:${e}/health`,t||r()),o=await(0,f.fetch)(`http://localhost:${e}/health`,{headers:n?{[h.LOCAL_SECRET_HEADER]:n}:{},signal:AbortSignal.timeout(1500)})
|
|
7
|
+
if(!o.ok)return null
|
|
8
|
+
const c=await o.json()
|
|
9
|
+
return"string"==typeof c?.projectPath?c.projectPath:null}catch{return null}}async function l(e){const t=o(e),r=Date.now(),l=y.get(t)
|
|
10
|
+
if(l&&r-l.at<3e4)return l.port
|
|
11
|
+
for(const o of[0,1]){1===o&&(d=null,p=0)
|
|
12
|
+
const l=n(e),a=await c(l,e)
|
|
13
|
+
if(a&&s(a)===s(t))return y.set(t,{port:l,at:r}),l}return y.delete(t),null}function s(e){try{return(0,i.realpathSync)(e)}catch{return e}}function a(){const e=Date.now()
|
|
14
|
+
return e-E>3e4&&(E=e,l().then(e=>{null===e&&(d=null,p=0,console.error(`[alchemy] the recorded action-server port does not serve ${o()}: re-reading it. If this repeats, the server for this project is not running.`))}).catch(()=>{})),`http://localhost:${n()}`}Object.defineProperty(exports,"__esModule",{value:!0}),exports.getActionServerPort=n,exports.verifiedActionServerPort=l,exports.getActionServerBaseUrl=a,exports.actionServerFetch=function(e,t){S||(S=new f.Agent({headersTimeout:0,bodyTimeout:0}))
|
|
15
|
+
const n=`${a()}${e}`,o=(0,h.localSecretForUrl)(n,r()),c=new Headers(t?.headers)
|
|
16
|
+
return o&&c.set(h.LOCAL_SECRET_HEADER,o),(0,f.fetch)(n,{...t,headers:c,dispatcher:S})}
|
|
17
|
+
const i=t(79896),u=t(16928),f=t(9956),h=t(41950)
|
|
18
|
+
let d=null,p=0
|
|
19
|
+
const y=new Map
|
|
20
|
+
let S,E=0},41950(e,exports,t){function r(e){try{const t=JSON.parse(l.default.readFileSync(s.default.join(e,a),"utf8"))
|
|
21
|
+
return{port:"number"==typeof t.port?t.port:void 0,secret:"string"==typeof t.secret&&t.secret?t.secret:void 0}}catch{return{}}}function n(e,t){const n=function(e){try{const t=new URL(e),r=t.hostname.toLowerCase()
|
|
22
|
+
if("127.0.0.1"!==r&&"localhost"!==r&&"[::1]"!==r)return null
|
|
23
|
+
if("http:"!==t.protocol&&"ws:"!==t.protocol)return null
|
|
24
|
+
const n=Number(t.port||80)
|
|
25
|
+
return Number.isFinite(n)?n:null}catch{return null}}(e)
|
|
26
|
+
if(null===n)return null
|
|
27
|
+
const o=Date.now()
|
|
28
|
+
return(!i||i.projectPath!==t||o-i.at>2e3)&&(i={projectPath:t,at:o,...r(t)}),i.port===n&&i.secret?i.secret:null}var o=this&&this.__importDefault||function(e){return e&&e.__esModule?e:{default:e}}
|
|
29
|
+
Object.defineProperty(exports,"__esModule",{value:!0}),exports.LOCAL_SECRET_HEADER=void 0,exports.newLocalSecret=function(){return(0,c.randomBytes)(24).toString("base64url")},exports.writeActionServerFile=function(e,t,r){const n=s.default.join(e,a)
|
|
30
|
+
l.default.mkdirSync(s.default.dirname(n),{recursive:!0})
|
|
31
|
+
const o=`${n}.${process.pid}.tmp`
|
|
32
|
+
l.default.writeFileSync(o,JSON.stringify({port:t,secret:r},null,2),{encoding:"utf8",mode:384}),l.default.renameSync(o,n)
|
|
33
|
+
try{l.default.chmodSync(n,384)}catch{}},exports.readActionServerFile=r,exports.secretMatches=function(e,t){if("string"!=typeof e||!e||!t)return!1
|
|
34
|
+
const r=Buffer.from(e),n=Buffer.from(t)
|
|
35
|
+
return r.length===n.length&&(0,c.timingSafeEqual)(r,n)},exports.localSecretForUrl=n,exports.installLocalSecretFetch=function(e=()=>process.env.ALCHEMY_PROJECT_PATH||process.cwd()){if("function"!=typeof globalThis.fetch)return
|
|
36
|
+
if(u&&globalThis.fetch===u)return
|
|
37
|
+
const t=globalThis.fetch.bind(globalThis),r=async(r,o)=>{try{const c="string"==typeof r?r:r instanceof URL?r.href:r?.url,l=c?n(c,e()):null
|
|
38
|
+
if(l){const e=new Headers(r&&"object"==typeof r&&"headers"in r?r.headers:void 0)
|
|
39
|
+
return new Headers(o?.headers).forEach((t,r)=>e.set(r,t)),e.set(exports.LOCAL_SECRET_HEADER,l),t(r,{...o??{},headers:e})}}catch{}return t(r,o)}
|
|
40
|
+
globalThis.fetch=r,u=r},exports.resetLocalSecretCache=function(){i=null}
|
|
41
|
+
const c=t(76982),l=o(t(79896)),s=o(t(16928))
|
|
42
|
+
exports.LOCAL_SECRET_HEADER="x-alchemy-local"
|
|
43
|
+
const a=s.default.join(".alchemy_lab","action-server.json")
|
|
44
|
+
let i=null,u=null}}
|
package/dist/478.js
CHANGED
|
@@ -1,21 +1,5 @@
|
|
|
1
1
|
"use strict"
|
|
2
|
-
exports.ids=[478],exports.modules={
|
|
3
|
-
Object.defineProperty(exports,"__esModule",{value:!0}),exports.DefaultProjectFileSystem=void 0
|
|
4
|
-
const i=r(t(79896)),o=r(t(16928)),s=t(14139)
|
|
5
|
-
exports.DefaultProjectFileSystem=class{constructor(e){this.logger=e.child({component:"project-file-system"})}async readProjectFile(e){try{const t=o.default.join(e,"project.json"),r=o.default.join(e,s.ALCHEMY_DIR_NAME,"project.json")
|
|
6
|
-
let a=r
|
|
7
|
-
if(i.default.existsSync(t))a=t,this.logger.info("Found project file in base directory",{path:a})
|
|
8
|
-
else{if(!i.default.existsSync(r))return this.logger.info("Project file does not exist in either location",{directPath:t,nestedPath:r}),null
|
|
9
|
-
this.logger.info("Found project file in alchemy_lab subdirectory",{path:a})}const n=await i.default.promises.readFile(a,"utf8"),c=JSON.parse(n)
|
|
10
|
-
return c.id?(this.logger.info("Read project file successfully",{projectId:c.id,path:a}),c):(this.logger.warn("Project file has no ID",{path:a}),null)}catch(t){return this.logger.error("Failed to read project file",{basePath:e,error:t instanceof Error?t.stack:String(t)}),null}}async writeProjectFile(e,t){try{const r=o.default.join(t,"project.json"),a=o.default.join(t,s.ALCHEMY_DIR_NAME,"project.json")
|
|
11
|
-
let n=r
|
|
12
|
-
!i.default.existsSync(r)&&i.default.existsSync(a)?(n=a,this.logger.info("Using existing nested path for project file",{path:n})):this.logger.info("Using direct path for project file",{path:n}),await this.ensureDirectoryExists(o.default.dirname(n)),await i.default.promises.writeFile(n,JSON.stringify(e,null,2),"utf8"),this.logger.info("Wrote project file successfully",{projectId:e.id,path:n})}catch(r){throw this.logger.error("Failed to write project file",{projectId:e.id,basePath:t,error:r instanceof Error?r.stack:String(r)}),r}}async ensureDirectoryExists(e){try{i.default.existsSync(e)||(await i.default.promises.mkdir(e,{recursive:!0}),this.logger.info("Created directory",{path:e}))}catch(t){throw this.logger.error("Failed to create directory",{path:e,error:t instanceof Error?t.stack:String(t)}),t}}}},18029(e,exports,t){var r=this&&this.__importDefault||function(e){return e&&e.__esModule?e:{default:e}}
|
|
13
|
-
Object.defineProperty(exports,"__esModule",{value:!0}),exports.ProjectIDBackwardCompat=exports.ProjectIDFactory=exports.ProjectID=void 0
|
|
14
|
-
const i=r(t(76982))
|
|
15
|
-
class o{static create(){return exports.ProjectIDFactory.create()}static fromString(e){return exports.ProjectIDFactory.fromString(e)}static isValid(e){return exports.ProjectIDFactory.isValid(e)}constructor(e){this.id=e}toString(){return this.id}equals(e){return this.id===e.toString()}isStandardFormat(){return this.id.includes("_")&&this.id.startsWith("prj_")}}exports.ProjectID=o,exports.ProjectIDFactory={create(){const e=Date.now().toString().substring(5),t=i.default.randomBytes(4).toString("hex")
|
|
16
|
-
return o.fromString(`prj_${e}_${t}`)},fromString(e){return this.isValid(e)?new o(e):null},isValid(e){if(!e||"string"!=typeof e||e.length<5||!e.startsWith("prj"))return!1
|
|
17
|
-
if(e.includes("_")){const t=e.split("_")
|
|
18
|
-
return t.length>=3&&"prj"===t[0]}return!1}},exports.ProjectIDBackwardCompat={create:exports.ProjectIDFactory.create,fromString:exports.ProjectIDFactory.fromString,isValid:exports.ProjectIDFactory.isValid},Object.assign(o,exports.ProjectIDBackwardCompat)},75478(e,exports,t){exports.ProjectSynchronizer=exports.ProjectFileSystem=exports.ProjectRegistry=void 0
|
|
2
|
+
exports.ids=[478],exports.modules={75478(e,exports,t){exports.ProjectSynchronizer=exports.ProjectFileSystem=exports.ProjectRegistry=void 0
|
|
19
3
|
var r=t(89955)
|
|
20
4
|
Object.defineProperty(exports,"ProjectRegistry",{enumerable:!0,get:function(){return r.ProjectRegistry}})
|
|
21
5
|
var i=t(53102)
|
|
@@ -33,47 +17,23 @@ let t=0
|
|
|
33
17
|
for(const r of e)try{const e=o.default.join(this.options.storageDirectory,r),s=i.default.readFileSync(e,"utf8"),a=JSON.parse(s)
|
|
34
18
|
if(!a.id){this.logger.warn("Skipping project file with missing ID",{filePath:e})
|
|
35
19
|
continue}this.register(a,{saveToFile:!1}),t++}catch(e){this.logger.error("Error loading project file",{file:r,error:e instanceof Error?e.stack:String(e)})}this.logger.info("Finished loading projects from disk",{totalLoaded:t,totalFiles:e.length})}catch(e){this.logger.error("Failed to load projects from disk",{error:e instanceof Error?e.stack:String(e)})}}setStorageDirectory(e){this.options.storageDirectory=e,this.logger.info("Set storage directory",{directory:e})}setPersistToDisk(e){this.options.persistToDisk=e,this.logger.info("Set persist to disk",{persistToDisk:e})}}},52568(e,exports,t){var r=this&&this.__importDefault||function(e){return e&&e.__esModule?e:{default:e}}
|
|
36
|
-
Object.defineProperty(exports,"__esModule",{value:!0}),exports.ProjectSynchronizer=void 0
|
|
37
|
-
const i=r(t(16928)),o=t(
|
|
38
|
-
exports.ProjectSynchronizer=class{constructor(e,t,r,i,o={}){this.logger=e.child({component:"project-synchronizer"}),this.registry=t,this.remoteApi=r,this.fileSystem=i,this.options={createRemoteProjects:o.createRemoteProjects??!0,maxRetryAttempts:o.maxRetryAttempts??3,retryDelayMs:o.retryDelayMs??1e3},this.logger.info("ProjectSynchronizer initialized",{options:this.options})}async ensureProjectExists(e){
|
|
39
|
-
this.
|
|
40
|
-
|
|
41
|
-
if(
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
{this.logger.info("\u{1f4de} SYNC-TRACE: Creating project on remote server",{callId:t,projectId:e})
|
|
47
|
-
let r={id:e,name:"Remote Synchronized Project",description:"Automatically created during synchronization",status:"active"}
|
|
48
|
-
const i=this.registry.getProject(e)
|
|
49
|
-
i&&(this.logger.info("\u{1f4de} SYNC-TRACE: Using local project data",{callId:t,projectId:e,projectName:i.name}),r={...i})
|
|
50
|
-
try{this.logger.info("\u{1f4de} SYNC-TRACE: Calling remoteApi.createProject",{callId:t,projectId:e,projectName:r.name})
|
|
51
|
-
const i=await this.remoteApi.createProject(r)
|
|
52
|
-
return this.logger.info("Create project API call succeeded",{returnedId:i?.id,returnedName:i?.name}),this.registry.register(i),this.logger.info("Successfully created project on remote server",{projectId:i.id,projectName:i.name}),i.id}catch(t){if(t&&"object"==typeof t&&"status"in t&&409===t.status)return this.logger.info("Project already exists on remote (409 conflict)",{projectId:e}),this.registry.markVerified(e),e
|
|
53
|
-
throw this.logger.error("Failed to create project on remote server",{projectId:e,error:t instanceof Error?t.stack:String(t),status:t?.status,message:t instanceof Error?t.message:String(t)}),t}}}catch(t){throw this.logger.error("Error verifying project existence",{projectId:e,error:t instanceof Error?t.stack:String(t),message:(0,s.getErrorMessage)(t)}),t}}async createProject(e,t){try{if(e.id){if(!o.ProjectIDFactory.isValid(e.id)){this.logger.warn("Invalid project ID format, generating new ID",{originalId:e.id})
|
|
54
|
-
const t=o.ProjectIDFactory.create().toString()
|
|
55
|
-
e.id=t}}else{const t=o.ProjectIDFactory.create().toString()
|
|
56
|
-
e.id=t,this.logger.info("Generated new project ID",{projectId:t})}const r=(new Date).toISOString(),i={id:e.id,name:e.name||"Unnamed Project",description:e.description||"No description provided",status:e.status||"active",createdAt:e.createdAt||r,updatedAt:e.updatedAt||r,metadata:e.metadata||{}}
|
|
57
|
-
if(this.registry.register(i),t&&await this.fileSystem.writeProjectFile(i,t),this.remoteApi.isOnline())try{this.logger.info("Syncing new project to remote server",{projectId:i.id}),await this.ensureProjectExists(i.id)}catch(e){this.logger.warn("Failed to sync new project to remote, will retry later",{projectId:i.id,error:e instanceof Error?e.message:String(e)})}return i}catch(t){throw this.logger.error("Failed to create project",{projectData:e,error:t instanceof Error?t.stack:String(t)}),t}}async syncAllProjects(e){try{if(!this.remoteApi.isOnline())return void this.logger.info("Skipping project synchronization - system is offline")
|
|
20
|
+
Object.defineProperty(exports,"__esModule",{value:!0}),exports.ProjectSynchronizer=exports.ProjectMissingOnRemote=void 0
|
|
21
|
+
const i=r(t(16928)),o=t(58824)
|
|
22
|
+
class s extends Error{constructor(e){super(`Project ${e} (from .alchemy_lab/project.json) was not found on the server. Its id is kept and no new project was registered.`),this.projectId=e,this.status=404,this.name="ProjectMissingOnRemote"}}exports.ProjectMissingOnRemote=s,exports.ProjectSynchronizer=class{constructor(e,t,r,i,o={}){this.logger=e.child({component:"project-synchronizer"}),this.registry=t,this.remoteApi=r,this.fileSystem=i,this.options={createRemoteProjects:o.createRemoteProjects??!0,maxRetryAttempts:o.maxRetryAttempts??3,retryDelayMs:o.retryDelayMs??1e3},this.logger.info("ProjectSynchronizer initialized",{options:this.options})}async ensureProjectExists(e){if(!this.remoteApi.isOnline())return e
|
|
23
|
+
if(this.registry.isVerified(e))return e
|
|
24
|
+
const t=await this.remoteApi.fetchProject(e)
|
|
25
|
+
if(t)return this.registry.register(t),e
|
|
26
|
+
const r=new s(e)
|
|
27
|
+
throw this.logger.error("Project in project.json is not on the server; keeping its id, registering nothing",{projectId:e,reason:"remote answered 404 for this project id"}),r}async createProject(e,t){if(!this.remoteApi.isOnline())throw new Error("Cannot register a new project while offline")
|
|
28
|
+
const{id:r,...i}=e,o=await this.remoteApi.createProject({...i,name:i.name||"Unnamed Project",status:i.status||"active"}),s=(new Date).toISOString(),a={id:o.id,name:o.name||i.name||"Unnamed Project",description:i.description||o.description||"",status:i.status||"active",createdAt:i.createdAt||s,updatedAt:s,metadata:i.metadata||{}}
|
|
29
|
+
return this.registry.register(a),t&&await this.fileSystem.writeProjectFile(a,t),this.logger.info("Registered new project",{projectId:a.id,basePath:t}),a}async syncAllProjects(e){try{if(!this.remoteApi.isOnline())return void this.logger.info("Skipping project synchronization - system is offline")
|
|
58
30
|
this.logger.info("Starting project synchronization from directory",{basePath:e})
|
|
59
31
|
const t=await this.fileSystem.readProjectFile(e)
|
|
60
32
|
if(!t||!t.id)return void this.logger.info("No valid local project found, skipping synchronization",{basePath:e})
|
|
61
33
|
this.logger.info("Found local project",{projectId:t.id,projectName:t.name}),this.logger.info("Registering project in registry before synchronization",{projectId:t.id,projectName:t.name}),this.registry.register(t),this.logger.info("Ensuring project exists on remote server",{projectId:t.id}),await this.ensureProjectExists(t.id)?(this.logger.info("Project exists on remote, checking metadata sync",{projectId:t.id,projectName:t.name,basePath:e}),t.metadata&&Object.keys(t.metadata).length>0&&(this.logger.info("Syncing project metadata to remote (async)",{projectId:t.id,metadataKeys:Object.keys(t.metadata)}),this.remoteApi.updateProject(t.id,{metadata:t.metadata}).then(()=>{this.logger.info("Project metadata synced successfully",{projectId:t.id})}).catch(e=>{this.logger.warn("Failed to sync project metadata",{projectId:t.id,error:e instanceof Error?e.message:String(e)})})),this.logger.info("Successfully synchronized project",{projectId:t.id,projectName:t.name,basePath:e})):this.logger.warn("Failed to verify/create project on remote server",{projectId:t.id,basePath:e})}catch(t){this.logger.error("Error during project synchronization",{basePath:e,error:t instanceof Error?t.stack:String(t)})}}async loadLocalProject(e){try{this.logger.info("Loading local project from directory",{basePath:e})
|
|
62
34
|
const t=await this.fileSystem.readProjectFile(e)
|
|
63
|
-
return t&&t.id?(this.registry.register(t),this.logger.info("Successfully loaded local project",{projectId:t.id,basePath:e}),t):(this.logger.info("No valid local project found",{basePath:e}),null)}catch(t){return this.logger.error("Error loading local project",{basePath:e,error:t instanceof Error?t.stack:String(t)}),null}}async getOrCreateProject(e,t={}){this.
|
|
64
|
-
try{this.logger.
|
|
65
|
-
const r=await this.loadLocalProject(e)
|
|
66
|
-
if(r){this.logger.info("Found existing local project",{projectId:r.id,projectName:r.name,basePath:e})
|
|
67
|
-
const t=this.remoteApi.isOnline()
|
|
68
|
-
if(this.logger.info("Checking online status for verification",{isOnline:t,projectId:r.id}),!t)return this.logger.info("Using existing project (offline, skipping server verification)",{projectId:r.id,basePath:e}),r
|
|
69
|
-
{this.logger.info("System is online - starting project verification",{projectId:r.id,basePath:e})
|
|
70
|
-
const t=await this.ensureProjectExists(r.id)
|
|
71
|
-
if(this.logger.info("Project verification completed",{projectId:r.id,exists:t,basePath:e}),t)return this.logger.info("Using existing project (verified on server)",{projectId:r.id,basePath:e}),r
|
|
72
|
-
this.logger.warn("Local project not found on server, creating new project",{invalidProjectId:r.id,basePath:e})}}this.logger.info("No existing project found, creating new one",{basePath:e}),t.name||(t.name=i.default.basename(e))
|
|
73
|
-
const o=await this.createProject(t,e)
|
|
74
|
-
return this.logger.info("Created new project for directory",{projectId:o.id,basePath:e}),o}catch(t){this.logger.error("Error getting or creating project",{basePath:e,error:t instanceof Error?t.stack:String(t)})
|
|
75
|
-
const r=await this.createProject({name:`Fallback Project for ${i.default.basename(e)}`,description:"Created as fallback due to error"},e)
|
|
76
|
-
return this.logger.info("Created fallback project due to error",{projectId:r.id,basePath:e}),r}}async verifyAndFixProjectName(e){try{if(!this.remoteApi.isOnline())return this.logger.info("Skipping project name verification - system is offline"),!0
|
|
35
|
+
return t&&t.id?(this.registry.register(t),this.logger.info("Successfully loaded local project",{projectId:t.id,basePath:e}),t):(this.logger.info("No valid local project found",{basePath:e}),null)}catch(t){return this.logger.error("Error loading local project",{basePath:e,error:t instanceof Error?t.stack:String(t)}),null}}async getOrCreateProject(e,t={}){const r=await this.loadLocalProject(e)
|
|
36
|
+
if(r){try{await this.ensureProjectExists(r.id)}catch(t){this.logger.warn("Could not verify the project on the server; using the id in project.json",{projectId:r.id,basePath:e,error:(0,o.getErrorMessage)(t)})}return r}return t.name||(t.name=i.default.basename(e)),this.createProject(t,e)}async verifyAndFixProjectName(e){try{if(!this.remoteApi.isOnline())return this.logger.info("Skipping project name verification - system is offline"),!0
|
|
77
37
|
if(this.registry.isVerifiedWithName&&this.registry.isVerifiedWithName(e.id,e.name))return this.logger.info("Project name already verified, skipping verification",{projectId:e.id,projectName:e.name}),!0
|
|
78
38
|
const t=await this.remoteApi.fetchProject(e.id)
|
|
79
39
|
if(!t)return this.logger.warn("Cannot verify project name - project not found on remote",{projectId:e.id}),!1
|
package/dist/579.js
CHANGED
|
@@ -1,11 +1,15 @@
|
|
|
1
1
|
"use strict"
|
|
2
2
|
exports.ids=[579],exports.modules={74579(e,exports,t){function n(e){const t=/(?:^|[\s:])([A-Za-z0-9_.+-]+): (?:command )?not found(?=\s|$)/m.exec(e)
|
|
3
|
-
return t?t[1]:null}async function
|
|
4
|
-
return(await
|
|
5
|
-
for(const
|
|
6
|
-
|
|
7
|
-
if(!
|
|
8
|
-
const
|
|
9
|
-
try{for(const
|
|
10
|
-
if(!e?.success||0!==
|
|
11
|
-
|
|
3
|
+
return t?t[1]:null}async function s(e,n,s){const{actionServerFetch:a}=await Promise.resolve().then(()=>t(79414))
|
|
4
|
+
return(await a(e,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify(n),signal:AbortSignal.timeout(s)})).json().catch(()=>({}))}exports.trialFailures=function(e){const t=[]
|
|
5
|
+
for(const s of e){const e=n(s.output)
|
|
6
|
+
s.needsEarlier?t.push(`${s.name}: fails with only the setup before it, and passes after the other commands ran (${s.output.replace(/\s+/g," ").trim().slice(0,160)}). A request's criteria checks run with the setup alone, in a clean checkout, so they would fail the same way. A step that prepares the tree (installs the project, generates files the tests import) goes in \`setup\`; a step that is a check in its own right goes in the same command, joined with &&`):e?t.push(`${s.name}: the environment has no \`${e}\` (the command ran, but the shell said "${e}: not found")`):0!==s.exit&&t.push(`${s.name}: exited ${s.exit}: ${s.output.replace(/\s+/g," ").trim().slice(0,240)}`)}return t},exports.trialRun=async function(e){const t=e.call??s,o=await t("/api/experiments/start",{sessionId:e.sessionId,environmentId:e.environmentId,...e.branchName?{branchName:e.branchName}:{}},18e4).catch(()=>null),i=o?.success?o?.data?.handle:null
|
|
7
|
+
if(!i)return null
|
|
8
|
+
const r=[]
|
|
9
|
+
try{for(const n of e.setup){const e=await t("/api/experiments/exec",{handle:i,command:n,timeoutMs:3e5,why:"trial of a check before it is registered (setup)"},32e4).catch(()=>null),s=e?.data??{}
|
|
10
|
+
if(!e?.success||0!==s.exit)return r.push({name:`setup: ${n.slice(0,60)}`,command:n,exit:"number"==typeof s.exit?s.exit:-1,output:`${s.stdout??""}\n${s.stderr??e?.error??""}`}),r}const s=async e=>{const n=1e3*Math.min(Math.max(e.timeout,10),300),s=await t("/api/experiments/exec",{handle:i,command:e.command,timeoutMs:n,why:"trial of a check before it is registered"},n+2e4).catch(()=>null),a=s?.data??{}
|
|
11
|
+
return{name:e.name,command:e.command,exit:"number"==typeof a.exit?a.exit:-1,output:`${a.stdout??""}\n${a.stderr??(s?.success?"":s?.error??"no result")}`}},o=new Map,c=[]
|
|
12
|
+
for(const t of[...e.commands].reverse()){let e=await s(t)
|
|
13
|
+
0===e.exit||n(e.output)||(0,a.exitMeansCouldNotRun)(e.exit)||(e=await s(t),0!==e.exit&&c.push(t)),o.set(t.name,e)}if(e.commands.length>1)for(const e of c)0===(await s(e)).exit&&o.set(e.name,{...o.get(e.name),needsEarlier:!0})
|
|
14
|
+
for(const t of e.commands)r.push(o.get(t.name))}finally{await t("/api/experiments/stop",{handle:i},3e4).catch(()=>null)}return r}
|
|
15
|
+
const a=t(44600)}}
|
package/dist/60.js
CHANGED
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
"use strict"
|
|
2
2
|
exports.ids=[60],exports.modules={49060(t,exports,e){var a=this&&this.__importDefault||function(t){return t&&t.__esModule?t:{default:t}}
|
|
3
|
-
Object.defineProperty(exports,"__esModule",{value:!0}),exports.ConfigManager=void 0,exports.createConfigManager=function(t){return new
|
|
4
|
-
const i=a(e(91943)),n=a(e(16928)),
|
|
5
|
-
class
|
|
6
|
-
return t.includes("node_modules")?
|
|
7
|
-
return{...e,...n}}catch(a){return"ENOENT"===a.code||this.logger.warn("Error reading config file, using defaults",{filePath:t,error:(0,
|
|
8
|
-
return this.readConfig(e,
|
|
9
|
-
await this.writeConfig(a,i),this.logger.info("Updated project config",{projectPath:t,updates:e})}async getProjectMetadata(t){const e=n.
|
|
3
|
+
Object.defineProperty(exports,"__esModule",{value:!0}),exports.ConfigManager=void 0,exports.createConfigManager=function(t){return new d(t)}
|
|
4
|
+
const i=a(e(91943)),n=e(20990),r=a(e(16928)),o=a(e(70857)),s=e(14139),l=e(58824),c={},g={remoteServerUrl:"https://api.alchemylabcode.com",nodePath:"node"}
|
|
5
|
+
class d{constructor(t){this.logger=t.child({component:"config-manager"}),this.installationConfigDir=this.getInstallationConfigDir()}getInstallationConfigDir(){const t=__dirname||process.cwd(),e=o.default.homedir()
|
|
6
|
+
return t.includes("node_modules")?r.default.join(e,".alchemy_lab","config"):r.default.join(e,".alchemy_lab","config-dev")}async ensureDirectory(t){try{await i.default.access(t)}catch(e){await i.default.mkdir(t,{recursive:!0}),this.logger.debug("Created directory",{dirPath:t})}}async readConfig(t,e){try{const a=await i.default.readFile(t,"utf8"),n=JSON.parse(a)
|
|
7
|
+
return{...e,...n}}catch(a){return"ENOENT"===a.code||this.logger.warn("Error reading config file, using defaults",{filePath:t,error:(0,l.getErrorMessage)(a)}),e}}async writeConfig(t,e){await this.ensureDirectory(r.default.dirname(t)),await i.default.writeFile(t,JSON.stringify(e,null,2),"utf8"),this.logger.debug("Wrote config file",{filePath:t})}async getProjectConfig(t){const e=r.default.join(t,s.ALCHEMY_DIR_NAME,"config.json")
|
|
8
|
+
return this.readConfig(e,c)}async updateProjectConfig(t,e){const a=r.default.join(t,s.ALCHEMY_DIR_NAME,"config.json"),i={...await this.getProjectConfig(t),...e}
|
|
9
|
+
await this.writeConfig(a,i),this.logger.info("Updated project config",{projectPath:t,updates:e})}async getProjectMetadata(t){const e=(0,n.identityPath)(t)
|
|
10
10
|
try{const t=await i.default.readFile(e,"utf8"),a=JSON.parse(t)
|
|
11
|
-
return{id:a.id,name:a.name,createdAt:a.createdAt,status:a.status}}catch(t){return"ENOENT"===t.code||this.logger.warn("Error reading project metadata",{projectJsonPath:e,error:(0,
|
|
12
|
-
return this.readConfig(t,
|
|
11
|
+
return{id:a.id,name:a.name,createdAt:a.createdAt,status:a.status}}catch(t){return"ENOENT"===t.code||this.logger.warn("Error reading project metadata",{projectJsonPath:e,error:(0,l.getErrorMessage)(t)}),null}}async getInstallationConfig(){const t=r.default.join(this.installationConfigDir,"config.json")
|
|
12
|
+
return this.readConfig(t,g)}async updateInstallationConfig(t){const e=r.default.join(this.installationConfigDir,"config.json"),a={...await this.getInstallationConfig(),...t}
|
|
13
13
|
await this.writeConfig(e,a),this.logger.info("Updated installation config",{updates:t})}async getEffectiveConfig(t){const[e,a,i]=await Promise.all([this.getProjectConfig(t),this.getProjectMetadata(t),this.getInstallationConfig()])
|
|
14
|
-
return{remoteServerUrl:i.remoteServerUrl||
|
|
14
|
+
return{remoteServerUrl:i.remoteServerUrl||g.remoteServerUrl,nodePath:i.nodePath||g.nodePath,projectId:a?.id,projectName:a?.name}}getInstallationConfigPath(){return this.installationConfigDir}}exports.ConfigManager=d}}
|
package/dist/776.js
CHANGED
|
@@ -1,25 +1,33 @@
|
|
|
1
1
|
"use strict"
|
|
2
|
-
exports.ids=[776],exports.modules={37776(
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
return e},
|
|
7
|
-
var e=
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
2
|
+
exports.ids=[776],exports.modules={37776(e,exports,t){function r(e,t){return new Promise(r=>{(0,u.execFile)("git",t,{cwd:e,maxBuffer:16777216},(e,t,i)=>{r({code:e?"number"==typeof e.code?e.code:1:0,stdout:String(t??""),stderr:String(i??"")})})})}async function i(e){return 0===(await r(e,["rev-parse","--verify","--quiet","HEAD"])).code}function s(e){try{return d.realpathSync(e)}catch{return h.resolve(e)}}function o(e){if(0===e.length)return""
|
|
3
|
+
const t=1===e.length
|
|
4
|
+
return`It leaves ${e.slice(0,3).join(", ")+(e.length>3?` and ${e.length-3} more`:"")} out of the history, because ${t?"it looks like it holds":"they look like they hold"} a password or key; ${t?"it stays":"they stay"} in the folder as ${t?"it is":"they are"}.`}var a,n=this&&this.__createBinding||(Object.create?function(e,t,r,i){void 0===i&&(i=r)
|
|
5
|
+
var s=Object.getOwnPropertyDescriptor(t,r)
|
|
6
|
+
s&&!("get"in s?!t.__esModule:s.writable||s.configurable)||(s={enumerable:!0,get:function(){return t[r]}}),Object.defineProperty(e,i,s)}:function(e,t,r,i){void 0===i&&(i=r),e[i]=t[r]}),c=this&&this.__setModuleDefault||(Object.create?function(e,t){Object.defineProperty(e,"default",{enumerable:!0,value:t})}:function(e,t){e.default=t}),l=this&&this.__importStar||(a=function(e){return a=Object.getOwnPropertyNames||function(e){var t=[]
|
|
7
|
+
for(var r in e)Object.prototype.hasOwnProperty.call(e,r)&&(t[t.length]=r)
|
|
8
|
+
return t},a(e)},function(e){if(e&&e.__esModule)return e
|
|
9
|
+
var t={}
|
|
10
|
+
if(null!=e)for(var r=a(e),i=0;i<r.length;i++)"default"!==r[i]&&n(t,e,r[i])
|
|
11
|
+
return c(t,e),t})
|
|
12
|
+
Object.defineProperty(exports,"__esModule",{value:!0}),exports.hasCommits=i,exports.ensureProjectRepository=async function(e){let t=null
|
|
13
|
+
if(!d.existsSync(h.join(e,".git"))){const i=await r(e,["rev-parse","--show-toplevel"])
|
|
12
14
|
if(0===i.code&&i.stdout.trim()){const o=s(i.stdout.trim())
|
|
13
|
-
if(o!==s(
|
|
15
|
+
if(o!==s(e)){const i=await r(e,["ls-files","--","."])
|
|
14
16
|
if(0!==i.code||i.stdout.trim())return{status:"failed",message:`This folder's files belong to the git repository at ${o}, so AlchemyLab will not create a second repository here. Start AlchemyLab in ${o} (requests branch from that repository's default branch), or run \`git init\` here yourself if a nested repository is really what you want.`}
|
|
15
|
-
|
|
16
|
-
const
|
|
17
|
-
if(0!==
|
|
18
|
-
await(0,
|
|
19
|
-
const
|
|
20
|
-
const
|
|
21
|
-
if(0!==
|
|
22
|
-
let
|
|
23
|
-
try{
|
|
24
|
-
|
|
25
|
-
|
|
17
|
+
t=o}}}if(d.existsSync(h.join(e,".git")))return await(0,f.ensureAlchemyIgnoreEntries)(e),await i(e)?{status:"existing",hasHistory:!0}:{status:"existing",hasHistory:!1,message:'This repository has no commits yet. Requests branch from your default branch, so make a first commit (for example `git add -A && git commit -m "Initial commit"`), then start AlchemyLab again.'}
|
|
18
|
+
const a=await r(e,["init","-q","-b","main"])
|
|
19
|
+
if(0!==a.code)return{status:"failed",message:`Could not create a git repository here: ${a.stderr.trim()||"git is not available"}. Install git and run \`git init\` in this folder.`}
|
|
20
|
+
await(0,f.ensureAlchemyIgnoreEntries)(e)
|
|
21
|
+
const n=[];(await r(e,["config","user.email"])).stdout.trim()||n.push("-c","user.name=AlchemyLab","-c","user.email=alchemylab@localhost")
|
|
22
|
+
const c=await r(e,["add","-A"])
|
|
23
|
+
if(0!==c.code)return{status:"failed",message:`Created the repository but could not record the folder: ${c.stderr.trim()}`}
|
|
24
|
+
let l="",u=[]
|
|
25
|
+
try{const t=await(0,m.holdBackStagedCredentials)(e)
|
|
26
|
+
l=t.note,u=t.held.map(e=>e.file)}catch(e){return{status:"failed",message:`Created the repository but could not check the folder for key material before its first commit: ${e instanceof Error?e.message:String(e)}`}}const g=(await r(e,["diff","--cached","--name-only"])).stdout.split("\n").filter(Boolean),p=g.length,b=await r(e,[...n,"commit","-q","--allow-empty","-m","Initial commit (AlchemyLab created this repository)"+(l?`\n\n${l}`:"")])
|
|
27
|
+
if(0!==b.code)return{status:"failed",message:`Created the repository but could not make its first commit: ${b.stderr.trim()}`}
|
|
28
|
+
const w=`${p} file${1===p?"":"s"}`,v=0===(0,y.codePaths)(g).length
|
|
29
|
+
return{status:"created",filesCommitted:p,message:(v?p>0?`AlchemyLab keeps a history of every change in this folder, starting with the ${w} already here.`:"AlchemyLab keeps a history of every change in this folder, starting now.":p>0?`No git repository here. Created a git repository and recorded the ${w} already here as its first commit.`:"No git repository here. Created a git repository with an empty first commit.")+(t?` This folder is inside the repository at ${t}, which tracks nothing here, so it has its own.`:"")+(l?` ${v?o(u):l}`:"")}},exports.plainHeldLine=o
|
|
30
|
+
const u=t(35317),d=l(t(79896)),h=l(t(16928)),f=t(89796),m=t(96511),y=t(71879)},71879(e,exports,t){exports.codePaths=function(e){return e.filter(e=>{const t=e.split("/")
|
|
31
|
+
return!(t.some(e=>e.startsWith("."))||r.DOC_PATH_RE.test(e)||i.test(e)||/^(licen[cs]e|copying|notice)(\.[a-z]+)?$/i.test(t[t.length-1]))})},t(35317)
|
|
32
|
+
const r=t(92456),i=(t(52232),t(87780),/\.(docx?|odt|ods|odp|rtf|xlsx?|pptx?|pages|numbers|key|pdf|epub|csv|tsv|png|jpe?g|gif|webp|svg|heic|tiff?|bmp|mp3|m4a|wav|mp4|mov)$/i)
|
|
33
|
+
new Set,new Map,new Map}}
|
package/dist/9.js
ADDED
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
"use strict"
|
|
2
|
+
exports.ids=[9,111],exports.modules={56111(e,exports,t){async function r(e,t){if(t){if(!s||Date.now()-s.at>3e4)try{const t=await e.apiClient.get(`/api/projects/${e.projectId}/session-request-associations?activeOnly=true&limit=500`),r=t?.data??t??[],o=new Map
|
|
3
|
+
for(const e of r)e?.opencodeSessionId&&e?.requestLocalId&&o.set(e.opencodeSessionId,e.requestLocalId)
|
|
4
|
+
s={at:Date.now(),bySession:o}}catch(t){e.logger.debug?.("MCP receipt: could not read associations",{error:(0,o.getErrorMessage)(t)}),s=s??{at:Date.now(),bySession:new Map}}return s.bySession.get(t)}}exports.requestForSession=r,exports.openMcpReceipt=async function(e,t){const s=await r(e,t.sessionId??""),a=t.target?` (${t.target})`:"",i=`${t.tool} on the "${t.connection}" MCP server${a}`,l=t.allowed?`Called ${i}`:`Did not run ${i}: ${t.reason}`,c={connection:t.connection,tool:t.tool,target:t.target??null,gate:t.verdict,status:t.allowed?"started":"refused",sessionId:t.sessionId??null,callId:t.callId??null,startedAt:(new Date).toISOString()}
|
|
5
|
+
try{const r=await e.apiClient.post(`/api/projects/${e.projectId}/tool-records`,{...s?{requestId:s}:{},type:"mcp-call",...t.sessionId?{cliOrigin:{providerId:"opencode",sessionId:t.sessionId,createdAt:(new Date).toISOString()}}:{},metadata:c,note:l}),o=r?.data?.id??r?.id
|
|
6
|
+
t.allowed&&t.callId&&o&&(n.set(t.callId,{recordId:String(o),startedAt:Date.now(),metadata:c}),function(){if(n.size<=500)return
|
|
7
|
+
const e=[...n.entries()].sort((e,t)=>e[1].startedAt-t[1].startedAt)
|
|
8
|
+
for(const[t]of e){if(n.size<=500)break
|
|
9
|
+
n.delete(t)}}())}catch(r){e.logger.error("MCP receipt could not be written",{connection:t.connection,tool:t.tool,error:(0,o.getErrorMessage)(r)})}},exports.recordIdForCall=function(e){if(e)return n.get(e)?.recordId},exports.closeMcpReceipt=async function(e,t){if(!t.callId)return
|
|
10
|
+
let r=n.get(t.callId)
|
|
11
|
+
if(r||(await new Promise(e=>setTimeout(e,250)),r=n.get(t.callId)),r){n.delete(t.callId)
|
|
12
|
+
try{await e.apiClient.patch(`/api/projects/${e.projectId}/tool-records/${r.recordId}`,{metadata:{...r.metadata,status:t.ok?"completed":"failed",durationMs:Date.now()-r.startedAt,finishedAt:(new Date).toISOString(),...t.outputPreview?{outputPreview:t.outputPreview.slice(0,500)}:{},...t.error?{error:String(t.error).slice(0,500)}:{}}})}catch(r){e.logger.warn("MCP receipt could not be closed",{callId:t.callId,error:(0,o.getErrorMessage)(r)})}}}
|
|
13
|
+
const o=t(58824),n=new Map
|
|
14
|
+
let s=null},82009(e,exports,t){exports.writeWebReceipt=async function(e,t){const a=function(e){const t=e.input??{},r=e.metadata??{},o=e.error?{error:s(e.error,300)}:{},a={tool:e.tool,...e.callId?{callId:e.callId}:{}}
|
|
15
|
+
if("websearch"===e.tool){const i=s(t.query,300)
|
|
16
|
+
if(!i)return null
|
|
17
|
+
const l=Number.isFinite(Number(r.resultCount))?Number(r.resultCount):0,c=Array.isArray(r.hits)?r.hits.filter(e=>"string"==typeof e?.url).slice(0,8).map(e=>({title:s(e.title,200),url:String(e.url)})):[],d="string"==typeof r.backend?r.backend:void 0
|
|
18
|
+
return{type:"web-search",note:e.error?`Search did not run for "${i}": ${s(e.error,160)}`:`Searched the web for "${i}": ${l} ${1===l?"result":"results"}${d?` (${n[d]??d})`:""}`,metadata:{...a,query:i,...d?{backend:d}:{},resultCount:l,hits:c,...o}}}if("webfetch"===e.tool){const n=String(t.url??"").trim()
|
|
19
|
+
if(!/^https?:\/\//i.test(n))return null
|
|
20
|
+
const i="string"==typeof r.finalUrl&&r.finalUrl?r.finalUrl:n,l="number"==typeof r.status?r.status:void 0
|
|
21
|
+
return{type:"read-site",note:e.error?`Could not read ${n}: ${s(e.error,160)}`:`Read ${i}`,metadata:{...a,url:n,finalUrl:i,title:"string"==typeof r.title?r.title:null,...void 0!==l?{status:l}:{},...o}}}return null}(t)
|
|
22
|
+
if(!a)return!1
|
|
23
|
+
try{const r=await(0,o.requestForSession)(e,t.sessionId??"")
|
|
24
|
+
return await e.apiClient.post(`/api/projects/${e.projectId}/tool-records`,{...r?{requestId:r}:{},type:a.type,...t.sessionId?{cliOrigin:{providerId:"opencode",sessionId:t.sessionId,createdAt:(new Date).toISOString()}}:{},metadata:a.metadata,note:a.note}),!0}catch(o){return e.logger.warn("web receipt could not be written",{tool:t.tool,error:(0,r.getErrorMessage)(o)}),!1}}
|
|
25
|
+
const r=t(58824),o=t(56111),n={"exa-key":"Exa",tavily:"Tavily",exa:"Exa, no key"},s=(e,t)=>{const r=String(e??"").replace(/\s+/g," ").trim()
|
|
26
|
+
return r.length>t?`${r.slice(0,t-1).trimEnd()}\u2026`:r}}}
|
package/dist/902.js
ADDED
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
"use strict"
|
|
2
|
+
exports.ids=[902],exports.modules={70902(e,exports,t){async function r(e,t){const r=String(e.command||"").trim()
|
|
3
|
+
if(!r)return{verdict:"refuse",reason:"empty command"}
|
|
4
|
+
const n=(0,a.denyFloor)(r,t)
|
|
5
|
+
if(n)return{verdict:"refuse",by:`policy: ${n.ruleId}`,reason:n.reason}
|
|
6
|
+
const o=(0,a.resolvePolicy)(r,{sandboxed:e.sandboxed,projectPath:e.projectPath,shadow:t})
|
|
7
|
+
return"deny"===o.verdict?{verdict:"refuse",by:`policy: ${o.ruleId}`,reason:o.reason}:{verdict:"ask",reason:"shadow"===(0,a.gateMode)("registration")?"the registration review is in shadow, so every registered command asks you":"the registration review is off, so every registered command asks you"}}exports.judgeRegistration=async function(e){const t=[],n=(0,a.gateMode)("registration"),o="off"===n?await r(e,t):await async function(e,t){const r=String(e.command||"").trim()
|
|
8
|
+
if(!r)return{verdict:"refuse",reason:"empty command"}
|
|
9
|
+
const n=(0,a.denyFloor)(r,t)
|
|
10
|
+
if(n)return{verdict:"refuse",by:`policy: ${n.ruleId}`,reason:n.reason}
|
|
11
|
+
const o=(0,a.resolvePolicy)(r,{sandboxed:e.sandboxed,projectPath:e.projectPath,shadow:t})
|
|
12
|
+
if("deny"===o.verdict)return{verdict:"refuse",by:`policy: ${o.ruleId}`,reason:o.reason}
|
|
13
|
+
if(e.blastRadius)return{verdict:"ask",reason:"it is an operation (it acts on a running system), and operations always ask"}
|
|
14
|
+
if(e.manual)return{verdict:"ask",reason:"Autonomy is at Manual, where every command an agent registers asks you"}
|
|
15
|
+
let s=(0,a.decideCommandGate)(e.gates,r,{agentGateEnabled:!!e.judge,sandboxed:e.sandboxed,projectPath:e.projectPath,shadow:t})
|
|
16
|
+
if(s.shadowJudge&&e.judge){const a=await e.judge(r).catch(e=>({verdict:"escalate",reason:`judge error: ${String(e).slice(0,100)}`}))
|
|
17
|
+
t.push({gate:"judge",would:"allow"===a.verdict?"allow":"ask",reason:a.reason})}if("agent"===s.action&&e.judge){const n=await e.judge(r).catch(e=>({verdict:"escalate",reason:`judge error: ${String(e).slice(0,100)}`}))
|
|
18
|
+
if("allow"===n.verdict)return{verdict:"on",by:"command judge",reason:n.reason}
|
|
19
|
+
const o=s.remaining??[]
|
|
20
|
+
if(s=o.length?(0,a.decideCommandGate)(o,r,{sandboxed:e.sandboxed,projectPath:e.projectPath,shadow:t}):{action:"block",gate:"agent",reason:`the command judge escalated: ${n.reason}`},"run"!==s.action)return{verdict:"ask",by:"command judge",reason:"the command reviewer could not confirm it is harmless on your machine (a script it cannot see into, a write, or the network)",detail:n.reason}}return"run"===s.action?e.gates.length?{verdict:"on",by:`policy: ${s.ruleId??"allow"}`,reason:s.reason??"on the allowlist"}:{verdict:"on",by:"no gates (sealed environment)",reason:"its environment runs commands sealed, with no gate"}:"block"===s.action&&"policy"===s.gate&&s.ruleId?{verdict:"refuse",by:`policy: ${s.ruleId}`,reason:s.reason??"refused"}:{verdict:"ask",reason:s.reason??"the gates would ask a person about it"}}(e,t)
|
|
21
|
+
let s=o
|
|
22
|
+
return"shadow"===n&&"refuse"!==o.verdict&&(t.push({gate:"registration",would:"on"===o.verdict?"allow":"ask",reason:`${o.by?`${o.by}: `:""}${o.reason}`}),s=await r(e,[])),"ask"===s.verdict&&e.accepted&&await e.accepted().catch(()=>!1)&&(s={verdict:"on",by:"you",reason:"you said yes to it on its proposal"}),t.length?{...s,shadow:t}:s},exports.acceptedOnProposal=function(e,t){const r=n(t)
|
|
23
|
+
return!!r&&e.some(e=>"user"===e?.answeredBy&&Array.isArray(e.response?.selectedOptions)&&e.response.selectedOptions.includes("register")&&o(e.content).includes(r))},exports.whereItRan=function(e,t,r){if(!t)return null
|
|
24
|
+
const a=new Set(r.map(e=>String(e||"").trim()).filter(Boolean)),n=e.filter(e=>"experiment"===e.source&&e.sessionId===t&&"block"!==e.action&&"denied"!==e.action&&"timeout"!==e.action),o=n.find(e=>a.has(String(e.command||"").trim()))??n[0]
|
|
25
|
+
return o?o.environmentName?{environmentName:o.environmentName}:{}:null}
|
|
26
|
+
const a=t(33521),n=e=>String(e||"").replace(/\s+/g," ").trim(),o=e=>"string"==typeof e?[...e.matchAll(/(`+)([^`]+?)\1/g)].map(e=>n(e[2].replace(/^[a-z]*\n/,""))):Array.isArray(e)?e.flatMap(o):e&&"object"==typeof e?Object.values(e).flatMap(o):[]}}
|
package/dist/912.js
CHANGED
|
@@ -1,17 +1,31 @@
|
|
|
1
1
|
"use strict"
|
|
2
|
-
exports.ids=[912],exports.modules={47912(
|
|
3
|
-
const
|
|
4
|
-
if((0,
|
|
5
|
-
if(/^[0-9a-f]{40,64}$/.test(
|
|
6
|
-
if(0===
|
|
7
|
-
return 0===
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
return
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
const
|
|
14
|
-
|
|
15
|
-
const
|
|
16
|
-
|
|
17
|
-
|
|
2
|
+
exports.ids=[912],exports.modules={47912(e,exports,t){function n(e,t){return new Promise(n=>{(0,a.execFile)("git",t,{cwd:e,timeout:1e4,maxBuffer:8388608,windowsHide:!0},(e,t)=>{n({code:e?1:0,stdout:String(t??"")})})})}async function s(e,t,s){if(!p.test(t))return null
|
|
3
|
+
const r=(0,u.requestWorktreePath)(e,t)
|
|
4
|
+
if((0,l.existsSync)((0,c.join)(r,".git"))){const e=(await n(r,["merge-base",s,"HEAD"])).stdout.trim()
|
|
5
|
+
if(/^[0-9a-f]{40,64}$/.test(e)){const[t,s]=await Promise.all([n(r,["diff","--name-only",e]),n(r,["ls-files","--others","--exclude-standard"])])
|
|
6
|
+
if(0===t.code)return Array.from(new Set([...h(t.stdout),...h(s.stdout)])).sort()}}const i=await n(e,["diff","--name-only",`${s}...requests/${t}`])
|
|
7
|
+
return 0===i.code?h(i.stdout).sort():null}function r(e){const t=/(?:^|[.!?)\]][ \t]+)[ \t>*-]*\**Touches\**:\**[ \t]*(.+)$/im.exec(String(e??""))
|
|
8
|
+
return t?t[1].split(/\.(?:\s|$)/)[0].split(/[,;]/).map(e=>e.replace(/\(.*?\)/g,"").replace(/[`'"]/g,"").trim().replace(/^\*\*|\*\*$/g,"").replace(/^\.\//,"").replace(/\.+$/,"")).filter(e=>e.length>0&&!/\s/.test(e)&&(e.includes("/")||e.includes(".")||e.includes("*"))):[]}function i(e,t){for(const n of e){if(n.includes("*")){if(new RegExp(`^${n.split("**").map(e=>e.split("*").map(e=>e.replace(/[.+?^${}()|[\]\\]/g,"\\$&")).join("[^/]*")).join(".*")}$`).test(t))return!0
|
|
9
|
+
continue}const e=n.replace(/\/+$/,"")
|
|
10
|
+
if(t===e||t.startsWith(`${e}/`))return!0}return!1}function o(e,t,n){return!!(t.areas??[]).some(t=>(e.areas??[]).includes(t))||!!i(e.touches??[],n)||(e.changed??[]).some(e=>e===n||i([n],e))}exports.W0=void 0,exports.withInFlightFiles=async function(e,t,a){const l=(Array.isArray(a?.inFlightOwners)?a.inFlightOwners.filter(e=>"string"==typeof e?.requestId):Array.isArray(a?.inFlightWithoutFiles)?a.inFlightWithoutFiles.map(e=>({requestId:e})):[]).filter(e=>p.test(e.requestId)).slice(0,40).map(e=>({requestId:e.requestId,state:"string"==typeof e.state?e.state:"",planStep:!0===e.planStep,description:"string"==typeof e.description?e.description:"",areas:Array.isArray(e.areas)?e.areas.filter(e=>"string"==typeof e):[]}))
|
|
11
|
+
if(!t||0===l.length)return t
|
|
12
|
+
try{let c=l.map(e=>({owner:e,files:null}))
|
|
13
|
+
const u="string"==typeof a?.inFlightOwnId&&p.test(a.inFlightOwnId)?a.inFlightOwnId:null
|
|
14
|
+
let d=[]
|
|
15
|
+
if(e){const t=await(0,f.resolveDefaultBranch)(e),r=await async function(e){const t=await n(e,["for-each-ref","--format=%(refname:short)","refs/heads/requests/"])
|
|
16
|
+
return new Set(h(t.stdout).map(e=>e.replace(/^requests\//,"")))}(e)
|
|
17
|
+
c=await Promise.all(l.map(async n=>({owner:n,files:r.has(n.requestId)?await s(e,n.requestId,t):null}))),u&&r.has(u)&&(d=await s(e,u,t)??[])}const w=function(e,t={}){const n=t.touches??[],s=new Map,a=new Map
|
|
18
|
+
for(const{owner:n,files:r}of e)for(const e of r??[])o(t,n,e)&&s.set(e,[...s.get(e)??[],n])
|
|
19
|
+
for(const{owner:n,files:s}of e){const e=new Set(s??[])
|
|
20
|
+
for(const s of r(n.description))!e.has(s)&&o(t,n,s)&&a.set(s,[...a.get(s)??[],n])}const l=Array.from(new Set([...s.keys(),...a.keys()])).sort()
|
|
21
|
+
if(0===l.length)return null
|
|
22
|
+
const c=e=>{const t=e.filter(e=>e.planStep).map(e=>e.requestId),n=e.filter(e=>!e.planStep).map(e=>e.requestId)
|
|
23
|
+
return g([...t.length?[`${t.length>1?"steps":"step"} ${g(t)}`]:[],...n])},u=l.slice(0,exports.W0).map(e=>{const t=s.get(e)??[],r=(a.get(e)??[]).filter(e=>!t.includes(e)),o=i(n,e)
|
|
24
|
+
return 0===t.length?`- ${c(r)} ${r.length>1?"plan":"plans"} to change ${e}${o?" too (your request names it as well)":""}`:`- ${e} is also being changed by ${g(t.map(e=>e.state?`${e.requestId} (${e.state})`:e.requestId))}${r.length?`; ${c(r)} ${r.length>1?"plan":"plans"} to change it`:""}`}),f=l.length>exports.W0?`\n- and ${l.length-exports.W0} more files`:""
|
|
25
|
+
return"[who else is changing which files, from git and the plan]\n"+u.join("\n")+f+"\n"+(a.size?"A file only another step plans to change is that step's: leave it to that step unless your criteria need it. ":"")+`Where you change a file another request is changing${a.size?" or plans to change":""} too, keep to your part of it: main comes into your branch as their work lands.`}(c,{touches:r("string"==typeof a?.inFlightOwnDescription?a.inFlightOwnDescription:""),changed:d,areas:Array.isArray(a?.inFlightOwnAreas)?a.inFlightOwnAreas.filter(e=>"string"==typeof e):[]})
|
|
26
|
+
if(!w)return t
|
|
27
|
+
const m=t.split("\n\n"),y=m.findIndex(e=>e.startsWith("[work in flight beside "))
|
|
28
|
+
return y<0?`${t}\n\n${w}`:(m.splice(y+1,0,w),m.join("\n\n"))}catch{return t}}
|
|
29
|
+
const a=t(31421),l=t(73024),c=t(76760),u=t(7202),f=t(52232)
|
|
30
|
+
exports.W0=20
|
|
31
|
+
const p=/^req\d{6}$/,h=e=>e.split("\n").map(e=>e.trim()).filter(Boolean),g=e=>e.length<=1?e.join(""):`${e.slice(0,-1).join(", ")} and ${e[e.length-1]}`}}
|