alchemylab 1.4.7 → 1.4.8
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/cli.js +33 -23
- package/dist/http-server.js +681 -631
- package/dist/index.js +302 -252
- package/dist/mcp-direct.js +2268 -2218
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -3,9 +3,9 @@ if(void 0!==r)return r.exports
|
|
|
3
3
|
var module=s[t]={exports:{}}
|
|
4
4
|
return o[t].call(module.exports,module,module.exports,e),module.exports}var t,r,n,o={184(e,exports,t){"use strict"
|
|
5
5
|
function r(e,t,r,n,o={}){const s=d.default.resolve(e)
|
|
6
|
-
if(
|
|
7
|
-
const i=new
|
|
8
|
-
return
|
|
6
|
+
if(R.has(s))return t.child({component:"mcp-server-registry"}).debug("Using existing server for path",{path:s}),R.get(s)
|
|
7
|
+
const i=new x(s,t,r,n,o)
|
|
8
|
+
return R.set(s,i),i}var n,o=this&&this.__createBinding||(Object.create?function(e,t,r,n){void 0===n&&(n=r)
|
|
9
9
|
var o=Object.getOwnPropertyDescriptor(t,r)
|
|
10
10
|
o&&!("get"in o?!t.__esModule:o.writable||o.configurable)||(o={enumerable:!0,get(){return t[r]}}),Object.defineProperty(e,n,o)}:function(e,t,r,n){void 0===n&&(n=r),e[n]=t[r]}),s=this&&this.__setModuleDefault||(Object.create?function(e,t){Object.defineProperty(e,"default",{enumerable:!0,value:t})}:function(e,t){e.default=t}),i=this&&this.__importStar||(n=function(e){return n=Object.getOwnPropertyNames||function(e){var t=[]
|
|
11
11
|
for(var r in e)({}).hasOwnProperty.call(e,r)&&(t[t.length]=r)
|
|
@@ -16,7 +16,7 @@ return s(t,e),t}),a=this&&this.__importDefault||function(e){return e&&e.__esModu
|
|
|
16
16
|
Object.defineProperty(exports,"__esModule",{value:!0}),exports.McpServer=void 0,exports.resetStdoutWrite=function(){process.stdout.write=P},exports.getMcpServer=r,exports.createServer=function(e,t,n,o,s={}){return r(e,t,n,o,s)}
|
|
17
17
|
const c=t(3807),l=t(8909),d=a(t(6928)),u=a(t(9896)),h=a(t(1943)),p=t(9567),g=t(3444),m=t(7660),f=t(1253),y=i(t(7478)),w=t(4139),b=new Set,I=t(9860),k=t(1472),v=t(3328),C=t(8955),_=t(3217),E=t(5278),S=t(9060),T=t(8824),q=(0,g.createLogger)({serviceName:"stdout-capture",console:!1,logToFile:!1}),P=process.stdout.write,j=process.argv.includes("--stdio")||"true"===process.env.MCP_DIRECT_MODE
|
|
18
18
|
!(0,g.isDebugToolsEnabled)()||j&&"true"!==process.env.DEBUG_STDOUT_CAPTURE||(process.stdout.write=function(e){try{return(0,g.isDebugToolsEnabled)()&&"true"===process.env.DEBUG_LOGGING?.toLowerCase()&&"string"==typeof e&&!e.trim().startsWith('{"jsonrpc":"2.0"')&&e.trim().length>0&&q.debug("Stdout output",{content:e.substring(0,100),length:e.length}),P.call(process.stdout,e)}catch(e){return q.error("Error in safeStdoutWrite",{error:e+""}),!0}})
|
|
19
|
-
class
|
|
19
|
+
class x{constructor(e,t,r,n,o={}){this.git=null,this.currentSSEConnection=null,this.stdioTransport=null,this.isInitializing=!1,this.isInitialized=!1,this.logger=t.child({component:"mcp-server"}),this.logger.info("Creating McpServer instance",{basePath:e,remoteServerUrl:n,hasExistingProjectId:!!o.existingProjectId}),this.basePath=e,this.alchemyPath=d.default.join(e,w.ALCHEMY_DIR_NAME),this.metrics=r,this.remoteServerUrl=n,this.existingProjectId=o.existingProjectId,this.gitBinary=(0,l.detectGitBinary)(),this.logger.info("Detected git binary",{gitBinary:this.gitBinary,version:(0,l.getGitVersion)()}),this.projectContext=new m.ProjectContext(e,t),this.tokenManager=new f.TokenManager(t,e,{remoteServerUrl:n}),this.configManager=new S.ConfigManager(t),this.logger.debug("Server paths initialized",{basePath:this.basePath,alchemyPath:this.alchemyPath}),this.server=new p.Server({name:"alchemy",version:"1.0.0"},{capabilities:{tools:{listChanged:!0}}}),this.metrics.incrementCounter("mcp_server_init_started",1),this.logger.info("Starting initialization for server instance"),this.initializationPromise=this.initialize()}get branchState(){if(!this.workspaceManager)return{currentBranch:null,activeRequestId:null,isOnMainBranch:!0}
|
|
20
20
|
const e=this.workspaceManager.getCurrentContext("__server__")
|
|
21
21
|
return{currentBranch:e.branchName,activeRequestId:e.requestId,isOnMainBranch:e.isMainBranch}}async updateBranchState(e,t){this.logger.debug("updateBranchState called - managed by WorkspaceManager",{branch:e,requestId:t})}async getCurrentBranchContext(){if(!this.workspaceManager)return{branch:null,requestId:null,isMain:!0}
|
|
22
22
|
const e=this.workspaceManager.getCurrentContext("__server__")
|
|
@@ -93,8 +93,8 @@ const r=await y.switchToBranch(this.git,n.branchName,this.logger,this.metrics)
|
|
|
93
93
|
r.success?this.logger.info("Successfully switched workspace to correct branch",{requestId:e,branchName:n.branchName}):this.logger.error("Failed to switch workspace to correct branch",{requestId:e,expectedBranch:n.branchName,error:r.message})}}catch(t){this.logger.error("Failed to verify workspace branch status",{requestId:e,workspacePath:n.basePath,error:t instanceof Error?t.message:t+""})}return this.logger.info("Switched to request context",{requestId:e,workspacePath:n.basePath,branchName:n.branchName}),{success:!0,message:"Switched to workspace for request "+e,worktreePath:n.basePath}}catch(t){const r=(0,T.getErrorMessage)(t)
|
|
94
94
|
return this.logger.error("Failed to switch to request context",{requestId:e,error:r}),{success:!1,message:"Failed to switch context: "+r}}}async getEffectiveBasePath(e){if(!this.workspaceManager||!e)return this.basePath
|
|
95
95
|
const t=await this.workspaceManager.getWorkspaceInfo(e)
|
|
96
|
-
return t?.path||this.basePath}}exports.McpServer=
|
|
97
|
-
const
|
|
96
|
+
return t?.path||this.basePath}}exports.McpServer=x
|
|
97
|
+
const R=new Map},213(e,exports,t){"use strict"
|
|
98
98
|
Object.defineProperty(exports,"__esModule",{value:!0}),exports.def=void 0
|
|
99
99
|
const r=t(6183),n=t(3707)
|
|
100
100
|
exports.def={name:"quick_write",description:"WHEN TO USE: trivial single-file edits only. For multi-file or feature work, spawn a coder via subagent_operations.\n\nCreate or update a file or document. Wraps the change in a request/task workflow that auto-completes.\n\nUse 'path' for filesystem files or 'documentId' for tracked documents.\nSet append:true to add content to existing content.\n\n`content` accepts a single string OR an array of lines (joined with \\n). PREFER the array form for files containing brackets, quotes, or code-like syntax (TOML, JSON, Python, YAML) \u2014 sidesteps the JSON-escaping foot-gun where multi-line content with `[` or `{` confuses the parser.\n\nRequires: title, description, path/documentId, content.",schema:r.QuickWriteSchema,annotations:{title:"Quick Write",readOnlyHint:!1,destructiveHint:!1,idempotentHint:!1},handler(e,t){return(0,n.handleQuickChange)(e,"write",t.context,t.apiClient,t.logger,t.metrics,t.mcpServer)}}},233(e,exports,t){"use strict"
|
|
@@ -165,33 +165,34 @@ default:t="open"}else t="open"
|
|
|
165
165
|
const n=Array.isArray(e.acceptanceCriteria)?e.acceptanceCriteria.map(r):[]
|
|
166
166
|
return{id:e.id,title:e.title,description:e.description,type:e.type,status:t,acceptanceCriteria:n,createdAt:e.createdAt,updatedAt:e.updatedAt,...e.projectId?{projectId:e.projectId}:{},...e.completionSummary?{completionSummary:e.completionSummary}:{},...e.skippedTestRunId?{skippedTestRunId:e.skippedTestRunId}:{},...e.completedAt?{completedAt:e.completedAt}:{},...e.metadata?{metadata:e.metadata}:{},...e.lockInfo?{lockInfo:e.lockInfo}:{}}}Object.defineProperty(exports,"__esModule",{value:!0}),exports.adaptApiAcceptanceCriterionToDomain=r,exports.adaptApiRequestToDomain=n,exports.adaptApiRequestsToDomain=function(e){return e.map(n)}
|
|
167
167
|
const o=t(6756)},405(e,exports,t){"use strict"
|
|
168
|
-
Object.defineProperty(exports,"__esModule",{value:!0}),exports.handlePlanWrite=async function(e,t,l,d,u,h
|
|
169
|
-
try{const
|
|
170
|
-
switch(
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
return(0,
|
|
174
|
-
return
|
|
175
|
-
return
|
|
176
|
-
return
|
|
177
|
-
return u.incrementCounter("plan_write_total",1,{operation:"create-snapshot",success:!0}),(0,c.withAlchemyKind)({content:[{type:"text",text:`\u2705 **Plan Snapshot Created**\n\n**Plan:** ${m}\n**Version:** ${n.versionNumber}\n**Label:** ${e||"None"}\n**Summary:** ${t||"None"}\n**Created:** `+new Date(n.createdAt).toLocaleString()}]},"plan-snapshot")}case"restore":{const{versionNumber:e}=a,t=l.getDocumentClient(),r=await t.restoreToVersion(m,e)
|
|
178
|
-
return u.incrementCounter("plan_write_total",1,{operation:"restore",success:!0}),(0,c.withAlchemyKind)({content:[{type:"text",text:`\u2705 **Plan Restored**\n\n**Plan:** ${m}\n**Restored to Version:** ${e}\n**Filename:** ${r.filename}\n\nThe plan has been successfully restored to version ${e}.`}]},"plan-restore")}case"set-active":{const e=t.projectId
|
|
168
|
+
Object.defineProperty(exports,"__esModule",{value:!0}),exports.handlePlanWrite=async function(e,t,c,l,d,u,h){const p=l.child({tool:"plan_write"})
|
|
169
|
+
try{const i=e,{operation:l,planId:g}=i
|
|
170
|
+
switch(p.info("Processing plan_write",{operation:l}),l){case"create":{const e=await(0,s.handleCreatePlan)({name:i.name,content:i.content??""},t,c,p,d,u,h)
|
|
171
|
+
return d.incrementCounter("plan_write_total",1,{operation:"create",success:!e.isError}),(0,a.withAlchemyKind)(e,"plan-create")}case"update":{const e=await(0,r.handleUpdatePlan)({planId:g,content:i.content,name:i.name,metadata:{criteria:i.criteria,tickIntervalSeconds:i.tickIntervalSeconds,maxInFlight:i.maxInFlight,maxPerDay:i.maxPerDay,minIterations:i.minIterations,status:i.status,completionMode:i.completionMode}},t,c,p,d)
|
|
172
|
+
return d.incrementCounter("plan_write_total",1,{operation:"update",success:!e.isError}),(0,a.withAlchemyKind)(e,"plan-update")}case"append":{const e=await(0,n.handleAppendPlan)({planId:g,content:i.content,name:i.name},c,p,d)
|
|
173
|
+
return d.incrementCounter("plan_write_total",1,{operation:"append",success:!e.isError}),(0,a.withAlchemyKind)(e,"plan-append")}case"replace":{const e=await(0,o.handleReplacePlan)({planId:g,old:i.old,new:i.new,name:i.name},c,p,d)
|
|
174
|
+
return d.incrementCounter("plan_write_total",1,{operation:"replace",success:!e.isError}),(0,a.withAlchemyKind)(e,"plan-replace")}case"create-snapshot":{const{versionLabel:e,changeSummary:t}=i,r=c.getDocumentClient(),n=await r.createVersionSnapshot(g,e,t)
|
|
175
|
+
return d.incrementCounter("plan_write_total",1,{operation:"create-snapshot",success:!0}),(0,a.withAlchemyKind)({content:[{type:"text",text:`\u2705 **Plan Snapshot Created**\n\n**Plan:** ${g}\n**Version:** ${n.versionNumber}\n**Label:** ${e||"None"}\n**Summary:** ${t||"None"}\n**Created:** `+new Date(n.createdAt).toLocaleString()}]},"plan-snapshot")}case"restore":{const{versionNumber:e}=i,t=c.getDocumentClient(),r=await t.restoreToVersion(g,e)
|
|
176
|
+
return d.incrementCounter("plan_write_total",1,{operation:"restore",success:!0}),(0,a.withAlchemyKind)({content:[{type:"text",text:`\u2705 **Plan Restored**\n\n**Plan:** ${g}\n**Restored to Version:** ${e}\n**Filename:** ${r.filename}\n\nThe plan has been successfully restored to version ${e}.`}]},"plan-restore")}case"set-active":{const e=t.projectId
|
|
179
177
|
if(!e)return{content:[{type:"text",text:"\u274c No project context available."}],isError:!0}
|
|
180
|
-
const r=
|
|
181
|
-
if(!n)return{content:[{type:"text",text:"\u274c Plan not found: "+
|
|
182
|
-
if("Plan"!==n.type)return{content:[{type:"text",text:`\u274c Document ${
|
|
183
|
-
const o=
|
|
184
|
-
await o.updateProject(e,{activePlanId:
|
|
178
|
+
const r=c.getDocumentClient(),n=await r.getDocument(g)
|
|
179
|
+
if(!n)return{content:[{type:"text",text:"\u274c Plan not found: "+g}],isError:!0}
|
|
180
|
+
if("Plan"!==n.type)return{content:[{type:"text",text:`\u274c Document ${g} is not a Plan (type: ${n.type}).`}],isError:!0}
|
|
181
|
+
const o=c.getProjectClient()
|
|
182
|
+
await o.updateProject(e,{activePlanId:g}),d.incrementCounter("plan_write_total",1,{operation:"set-active",success:!0})
|
|
185
183
|
const s=n.localId||n.id
|
|
186
|
-
return(0,
|
|
187
|
-
const r=t(7609),n=t(4419),o=t(2352),s=t(6656),i=t(
|
|
184
|
+
return(0,a.withAlchemyKind)({content:[{type:"text",text:`\u2705 **Active Plan Updated**\n\n**Plan:** ${s}\n**Filename:** ${n.filename}\n**Project:** ${e}\n\nThis plan is now the active project plan.`}]},"plan-set-active")}default:throw Error("Unknown plan_write operation: "+l)}}catch(e){return p.error("plan_write failed",{error:e instanceof Error?e.stack:e+""}),d.incrementCounter("plan_write_errors",1),{content:[{type:"text",text:"\u274c **Plan Write Failed:** "+(0,i.getErrorMessage)(e)}],isError:!0}}}
|
|
185
|
+
const r=t(7609),n=t(4419),o=t(2352),s=t(6656),i=t(8824),a=t(2272)},441(e,exports){"use strict"
|
|
188
186
|
Object.defineProperty(exports,"__esModule",{value:!0}),exports.BAD_REQUEST=exports.INTERNAL_ERROR=exports.NOT_FOUND=exports.FORBIDDEN=exports.UNAUTHORIZED=exports.VALIDATION_ERROR=exports.MCP_PROTOCOL_ERROR=exports.REQUEST_VALIDATION_FAILED=exports.REQUEST_ID_INVALID_FORMAT=exports.REQUEST_NOT_FOUND=exports.CONNECTION_ERROR=exports.SERVICE_UNAVAILABLE=exports.CONNECTION_TIMEOUT=exports.SERVER_ERROR=exports.NETWORK_ERROR=exports.TASK_VALIDATION_FAILED=exports.TASK_ID_INVALID_FORMAT=exports.TASK_NOT_FOUND=void 0,exports.TASK_NOT_FOUND="TASK_NOT_FOUND",exports.TASK_ID_INVALID_FORMAT="TASK_ID_INVALID_FORMAT",exports.TASK_VALIDATION_FAILED="TASK_VALIDATION_FAILED",exports.NETWORK_ERROR="NETWORK_ERROR",exports.SERVER_ERROR="SERVER_ERROR",exports.CONNECTION_TIMEOUT="CONNECTION_TIMEOUT",exports.SERVICE_UNAVAILABLE="SERVICE_UNAVAILABLE",exports.CONNECTION_ERROR="CONNECTION_ERROR",exports.REQUEST_NOT_FOUND="REQUEST_NOT_FOUND",exports.REQUEST_ID_INVALID_FORMAT="REQUEST_ID_INVALID_FORMAT",exports.REQUEST_VALIDATION_FAILED="REQUEST_VALIDATION_FAILED",exports.MCP_PROTOCOL_ERROR="MCP_PROTOCOL_ERROR",exports.VALIDATION_ERROR="VALIDATION_ERROR",exports.UNAUTHORIZED="UNAUTHORIZED",exports.FORBIDDEN="FORBIDDEN",exports.NOT_FOUND="NOT_FOUND",exports.INTERNAL_ERROR="INTERNAL_ERROR",exports.BAD_REQUEST="BAD_REQUEST"},509(e,exports,t){"use strict"
|
|
189
187
|
Object.defineProperty(exports,"__esModule",{value:!0}),exports.def=void 0
|
|
190
188
|
const r=t(6183),n=t(9968)
|
|
191
189
|
exports.def={name:"update_specialization",description:"Update your specialization summary (\u2264500 chars) \u2014 a description of your accumulated domain expertise. Optionally pass specializationHeadline (\u226480 chars) for a short tagline shown next to your name in compact UI surfaces. Keep both current as you work.",schema:r.UpdateSpecializationSchema,annotations:{title:"Update Specialization",readOnlyHint:!1,destructiveHint:!1,idempotentHint:!0},handler(e,t){return(0,n.handleUpdateSpecialization)(e,t.logger,t.apiClient??void 0,t.cliOrigin)}}},542(e,exports,t){"use strict"
|
|
192
190
|
Object.defineProperty(exports,"__esModule",{value:!0}),exports.debugDefs=void 0
|
|
193
191
|
const r=t(1569),n=t(5997),o=t(8349),s=t(9852),i=t(9422),a=r.z.object({}),c=r.z.object({requestId:r.z.string().optional().describe("Request ID to search for")})
|
|
194
|
-
exports.debugDefs=[{name:"debug_multi_agent_status",description:"Debug tool to check multi-agent mode status, worktree state, and configuration",schema:a,annotations:{title:"Debug Multi-Agent Status",readOnlyHint:!0},debugOnly:!0,readOnly:!0,async handler(e,t){return{content:[{type:"text",text:await(0,n.handleDebugMultiAgentStatus)(e,t.context,t.logger,t.metrics)}]}}},{name:"debug_git_log",description:"Debug tool to examine git log and search for merge commits",schema:a,annotations:{title:"Debug Git Log",readOnlyHint:!0},debugOnly:!0,readOnly:!0,handler(e,t){return(0,o.handleDebugGitLog)(e,t.context,t.logger,t.metrics)}},{name:"debug_git_log_request",description:"Debug tool to examine git log for a specific request",schema:c,annotations:{title:"Debug Git Log Request",readOnlyHint:!0},debugOnly:!0,readOnly:!0,handler(e,t){return(0,s.handleDebugGitLogRequest)(e,t.context,t.logger,t.metrics)}},{name:"debug_request_file_history",description:"Debug tool to test git merge commit search patterns for request file history",schema:c,annotations:{title:"Debug Request File History",readOnlyHint:!0},debugOnly:!0,readOnly:!0,handler(e,t){return(0,i.handleDebugRequestFileHistory)(e,t.context,t.apiClient,t.logger,t.metrics)}}]},
|
|
192
|
+
exports.debugDefs=[{name:"debug_multi_agent_status",description:"Debug tool to check multi-agent mode status, worktree state, and configuration",schema:a,annotations:{title:"Debug Multi-Agent Status",readOnlyHint:!0},debugOnly:!0,readOnly:!0,async handler(e,t){return{content:[{type:"text",text:await(0,n.handleDebugMultiAgentStatus)(e,t.context,t.logger,t.metrics)}]}}},{name:"debug_git_log",description:"Debug tool to examine git log and search for merge commits",schema:a,annotations:{title:"Debug Git Log",readOnlyHint:!0},debugOnly:!0,readOnly:!0,handler(e,t){return(0,o.handleDebugGitLog)(e,t.context,t.logger,t.metrics)}},{name:"debug_git_log_request",description:"Debug tool to examine git log for a specific request",schema:c,annotations:{title:"Debug Git Log Request",readOnlyHint:!0},debugOnly:!0,readOnly:!0,handler(e,t){return(0,s.handleDebugGitLogRequest)(e,t.context,t.logger,t.metrics)}},{name:"debug_request_file_history",description:"Debug tool to test git merge commit search patterns for request file history",schema:c,annotations:{title:"Debug Request File History",readOnlyHint:!0},debugOnly:!0,readOnly:!0,handler(e,t){return(0,i.handleDebugRequestFileHistory)(e,t.context,t.apiClient,t.logger,t.metrics)}}]},577(e,exports,t){"use strict"
|
|
193
|
+
Object.defineProperty(exports,"__esModule",{value:!0}),exports.def=void 0
|
|
194
|
+
const r=t(6183),n=t(5652)
|
|
195
|
+
exports.def={name:"quest_audit_complete",description:'Signal that the active quest\'s acceptance criteria are met (alchemist-only).\n\nUse this at the end of a quest tick when, after auditing the worktree and any new evidence against the quest\'s criteria, every requirement is satisfied. Calling this does NOT immediately close the quest \u2014 the server enforces a consecutive-audit gate.\n\nWhat happens per call:\n\u2022 consecutiveDoneAudits is bumped by 1.\n\u2022 If the new counter is below minIterations, the tool returns a "need more consistent audits" message. Do not spawn work to "fix" that \u2014 only spawn work if you find actual remaining criteria. Just audit again on the next tick.\n\u2022 If the counter reaches minIterations, status flips based on completionMode:\n - audit-then-pending (default): status \u2192 pending_review, your summary + evidence are stored on the quest. Ticks stop. The user reviews and either closes or reopens.\n - auto-close: status \u2192 closed. The quest is terminal.\n - never-close: the tool returns an error. Do not retry on never-close quests.\n\nWhat resets the counter:\n\u2022 A request being created with this quest\'s questDocumentId. Spawning work means criteria are not actually met yet; the streak breaks and starts over.\n\nRequired: questId, summary. Optional: evidence (array of paths, request IDs, test names, etc.).',schema:r.QuestAuditCompleteSchema,annotations:{title:"Quest Audit Complete",readOnlyHint:!1,destructiveHint:!1,idempotentHint:!1},handler(e,t){return(0,n.handleQuestAuditComplete)(e,t.context,t.apiClient,t.logger,t.metrics)}}},700(e,exports,t){"use strict"
|
|
195
196
|
Object.defineProperty(exports,"__esModule",{value:!0}),exports.def=void 0
|
|
196
197
|
const r=t(6183),n=t(8037)
|
|
197
198
|
exports.def={name:"list_requests",description:"List requests with filtering options (status, type, dates) and pagination. Shows detailed request information including lock status to indicate which requests are currently in use by other agents.",schema:r.ListRequestsSchema,annotations:{title:"List Requests",readOnlyHint:!0},hidden:!0,readOnly:!0,handler(e,t){return(0,n.handleListRequests)(e,t.context,t.apiClient,t.logger,t.metrics)}}},857(module){"use strict"
|
|
@@ -326,21 +327,21 @@ return t},r(e)},function(e){if(e&&e.__esModule)return e
|
|
|
326
327
|
var t={}
|
|
327
328
|
if(null!=e)for(var s=r(e),i=0;i<s.length;i++)"default"!==s[i]&&n(t,e,s[i])
|
|
328
329
|
return o(t,e),t}),i=this&&this.__importDefault||function(e){return e&&e.__esModule?e:{default:e}}
|
|
329
|
-
Object.defineProperty(exports,"__esModule",{value:!0}),exports.registerApiRoutes=async function(e,r,n,o){const s=n.child({component:"api"}),i=r.getTokenManager(),q=process.env.REMOTE_SERVER_URL||"https://api.alchemylabcode.com",P=new f.AuthenticationManager(i,n.child({component:"auth-manager"})),j=P.getTokenSynchronizer(),
|
|
330
|
+
Object.defineProperty(exports,"__esModule",{value:!0}),exports.registerApiRoutes=async function(e,r,n,o){const s=n.child({component:"api"}),i=r.getTokenManager(),q=process.env.REMOTE_SERVER_URL||"https://api.alchemylabcode.com",P=new f.AuthenticationManager(i,n.child({component:"auth-manager"})),j=P.getTokenSynchronizer(),x=await P.getTokenString()||void 0
|
|
330
331
|
n.debug("Token retrieved from authentication manager")
|
|
331
|
-
const
|
|
332
|
+
const R=new b.ConnectionStatusManager(q,n.child({component:"connection-status-manager"}),o,{checkIntervalMs:3e4,timeoutMs:5e3}),M=new w.ProjectClient(q,n.child({component:"project-client"}),o,R,x)
|
|
332
333
|
j.registerClient(M)
|
|
333
|
-
const O=new k.TaskClient(q,n.child({component:"task-client"}),o,M,x
|
|
334
|
+
const O=new k.TaskClient(q,n.child({component:"task-client"}),o,M,R,x)
|
|
334
335
|
j.registerClient(O)
|
|
335
|
-
const $=new v.FileOperationsClient(q,n.child({component:"file-client"}),o,M,R
|
|
336
|
+
const $=new v.FileOperationsClient(q,n.child({component:"file-client"}),o,M,x,R)
|
|
336
337
|
j.registerClient($)
|
|
337
|
-
const D=new C.ProxyClient(q,n.child({component:"proxy-client"}),o,M,R
|
|
338
|
+
const D=new C.ProxyClient(q,n.child({component:"proxy-client"}),o,M,x,R)
|
|
338
339
|
j.registerClient(D)
|
|
339
|
-
const A=new _.RequestClient(q,n.child({component:"request-client"}),o,M,R
|
|
340
|
-
A.setAuthToken(
|
|
341
|
-
const F=new E.DocumentClient(q,n.child({component:"document-client"}),o,M,R
|
|
340
|
+
const A=new _.RequestClient(q,n.child({component:"request-client"}),o,M,x,R)
|
|
341
|
+
A.setAuthToken(x),(0,d.isDebugToolsEnabled)()&&n.debug("Explicitly set token on RequestClient",{tokenPresent:!!x}),j.registerClient(A)
|
|
342
|
+
const F=new E.DocumentClient(q,n.child({component:"document-client"}),o,M,x,R)
|
|
342
343
|
j.registerClient(F)
|
|
343
|
-
const N=new S.ToolRecordClient(q,n.child({component:"tool-record-client"}),o,M,R
|
|
344
|
+
const N=new S.ToolRecordClient(q,n.child({component:"tool-record-client"}),o,M,x,R)
|
|
344
345
|
j.registerClient(N)
|
|
345
346
|
const z=new T.ApiClient(P,M,O,$,A,F,N,D,n.child({component:"api-client"})),L=a.default.Router();(0,h.registerAuthRoutes)(L,{projectClient:M,taskClient:O,fileClient:$,authManager:P,apiClient:z},i,n)
|
|
346
347
|
const H=r.getContext();(0,p.registerConfigRoutes)(L,n,H.basePath),e.use("/api",L)
|
|
@@ -546,13 +547,13 @@ v.resolvedPath=_
|
|
|
546
547
|
let E=!1
|
|
547
548
|
try{E=(await p.default.stat(_)).isFile()}catch(e){const t=`Cannot access path ${_}: ${(0,I.getErrorMessage)(e)}`
|
|
548
549
|
throw v.errors.push(t),Error(t)}const S=C.maxResults||50,T=C.caseSensitive||!1,q=C.useRegex||!1,P=C.fileExtension,j=C.searchIn||"content"
|
|
549
|
-
let
|
|
550
|
-
if(0>
|
|
551
|
-
let
|
|
550
|
+
let x=void 0!==C.contextLines?C.contextLines:0
|
|
551
|
+
if(0>x?x=0:x>10&&(l.warn(`contextLines ${x} exceeds maximum of 10, clamping to 10`),x=10),!E&&!P)throw v.errors.push('File extension is required for directory search (use "*" for any extension, or formats like "ts", ".ts", "*.ts")'),(0,m.createValidationError)('File extension is required for directory search (use "*" for any extension, or formats like "ts", ".ts", "*.ts")')
|
|
552
|
+
let R,M=""
|
|
552
553
|
if(E)M="*"
|
|
553
554
|
else if("*"===P)M="*"
|
|
554
|
-
else if(P){let e=P;(e.startsWith("*.")||e.startsWith("*"))&&(e=e.substring(1)),M=e.startsWith(".")?e:"."+e}try{
|
|
555
|
-
throw v.errors.push(t),(0,m.createValidationError)(t)}if(v.patternInfo={needle:n,regex:
|
|
555
|
+
else if(P){let e=P;(e.startsWith("*.")||e.startsWith("*"))&&(e=e.substring(1)),M=e.startsWith(".")?e:"."+e}try{R=q?T?RegExp(n):RegExp(n,"i"):T?RegExp(o(n)):RegExp(o(n),"i")}catch(e){const t=`Invalid ${q?"regex":"search"} pattern: ${(0,I.getErrorMessage)(e)}`
|
|
556
|
+
throw v.errors.push(t),(0,m.createValidationError)(t)}if(v.patternInfo={needle:n,regex:R.toString(),caseSensitive:T,fileExtension:P,normalizedExtension:M},!E)try{const e=Date.now(),t=await p.default.readdir(_,{withFileTypes:!0}),r=[],n=[]
|
|
556
557
|
for(const e of t)e.isDirectory()?r.push(e.name):e.isFile()&&n.push(e.name)
|
|
557
558
|
v.initialScan={totalEntries:t.length,directories:r,files:n,firstFewFiles:n.slice(0,10),scanTime:Date.now()-e},v.phases.directoryListingTime=v.initialScan.scanTime}catch(e){const t="Failed to scan directory contents: "+(0,I.getErrorMessage)(e)
|
|
558
559
|
v.errors.push(t),l.error(t)}const O=E?"file":"directory"
|
|
@@ -574,7 +575,7 @@ o.errors.push(r),n.error(r)}return{matches:i,totalFiles:1}}(e,t,l,s,i,u)
|
|
|
574
575
|
const m={path:e,filesProcessed:0,filesMatched:0,subdirectories:0,errors:[]}
|
|
575
576
|
try{const{filesCount:n,fileMatchesCount:c,subdirCount:d,subdirStats:h}=await r(e,t,g,a,o,s,0,m,l,u)
|
|
576
577
|
return m.filesProcessed=n,m.filesMatched=c,m.subdirectories=d,i.directoryStats.push(m),h&&h.length>0&&i.directoryStats.push(...h),s.info("performLocalSearch completed",{totalFiles:n,matchesFound:g.length,directories:d+1}),{matches:g,totalFiles:n}}catch(t){const r="Error in performLocalSearch: "+(0,I.getErrorMessage)(t)
|
|
577
|
-
return m.errors.push(r),i.directoryStats.push(m),i.errors.push(r),s.error(r,{error:t instanceof Error?t.stack:t+"",searchPath:e}),{matches:g,totalFiles:m.filesProcessed}}}(_,
|
|
578
|
+
return m.errors.push(r),i.directoryStats.push(m),i.errors.push(r),s.error(r,{error:t instanceof Error?t.stack:t+"",searchPath:e}),{matches:g,totalFiles:m.filesProcessed}}}(_,R,{maxResults:S,fileExtension:M,searchIn:j,isFile:E,contextLines:x},M,l,v)
|
|
578
579
|
D=e.matches,A=e.totalFiles
|
|
579
580
|
const t=1e3
|
|
580
581
|
D.length>0&&D.length<=t?(D.sort(((e,t)=>void 0!==e.modifiedTime&&void 0!==t.modifiedTime?t.modifiedTime-e.modifiedTime:void 0!==e.modifiedTime&&void 0===t.modifiedTime?-1:void 0===e.modifiedTime&&void 0!==t.modifiedTime?1:0)),l.info(`Sorted ${D.length} matches by modification time (newest first)`)):D.length>t&&l.info(`Skipped sorting ${D.length} matches (exceeds hard cap of ${t} for performance)`),F=D.length,D.length>S&&(D=D.slice(0,S),l.info(`Limited results to ${S} (from ${F} total matches)`)),D.forEach((e=>{e.relativePath=function(e,t){const r=h.default.relative(e,t)
|
|
@@ -584,7 +585,7 @@ let N,z=""
|
|
|
584
585
|
try{if(t.workspaceManager){const e=t.workspaceManager.getCurrentContext(t.currentSessionId)
|
|
585
586
|
e.branchName&&!e.permanentBranch&&(z=e.isMainBranch?` (searched on main branch: ${e.branchName})`:` (searched on request branch: ${e.branchName}${e.requestId?" for "+e.requestId:""})`)}}catch(e){l.debug("Could not get branch context",{error:e}),z=" (branch context unavailable)"}l.debug("Search diagnostic information",{diagnostic:v})
|
|
586
587
|
const L="content"===j?"content":"filename"===j?"filenames":"content and filenames"
|
|
587
|
-
if(F>D.length?(N=`Found ${F} results for "${n}" (searching ${L})`,g&&(N+=" in "+g),P&&(N+=" with extension "+P),N+=`${z}. Showing first ${D.length}:\n\n`):(N=`Found ${D.length} results for "${n}" (searching ${L})`,g&&(N+=" in "+g),P&&(N+=" with extension "+P),N+=z+":\n\n"),D.length>0)if(
|
|
588
|
+
if(F>D.length?(N=`Found ${F} results for "${n}" (searching ${L})`,g&&(N+=" in "+g),P&&(N+=" with extension "+P),N+=`${z}. Showing first ${D.length}:\n\n`):(N=`Found ${D.length} results for "${n}" (searching ${L})`,g&&(N+=" in "+g),P&&(N+=" with extension "+P),N+=z+":\n\n"),D.length>0)if(x>0){const{filenameMatches:e,mergedGroups:t}=function(e,t){const r=e.filter((e=>"filename"===e.matchType)),n=e.filter((e=>"content"===e.matchType))
|
|
588
589
|
if(0===n.length)return{filenameMatches:r,mergedGroups:[]}
|
|
589
590
|
const o=new Map
|
|
590
591
|
for(const e of n){const t=o.get(e.file)||[]
|
|
@@ -592,7 +593,7 @@ t.push(e),o.set(e.file,t)}const i=[]
|
|
|
592
593
|
for(const[e,r]of o.entries()){r.sort(((e,t)=>e.line-t.line))
|
|
593
594
|
let e=[r[0]]
|
|
594
595
|
for(let n=1;n<r.length;n++){const o=e[e.length-1],a=r[n],c=o.line+t
|
|
595
|
-
a.line-t>c+1?(i.push(s(e,t)),e=[a]):e.push(a)}e.length>0&&i.push(s(e,t))}return{filenameMatches:r,mergedGroups:i}}(D,
|
|
596
|
+
a.line-t>c+1?(i.push(s(e,t)),e=[a]):e.push(a)}e.length>0&&i.push(s(e,t))}return{filenameMatches:r,mergedGroups:i}}(D,x),r=[]
|
|
596
597
|
e.forEach((e=>{r.push(e.relativePath+" [filename match]")})),t.forEach((e=>{const t=[]
|
|
597
598
|
e.lines.forEach((e=>{e.isMatch?t.push(`> ${e.lineNumber}: ${e.content}`):t.push(` ${e.lineNumber}: ${e.content}`)})),r.push(`${e.relativePath}:\n${t.join("\n")}`)})),N+=r.join("\n\n")}else N+=await async function(e){const t=e.filter((e=>"filename"===e.matchType)),r=e.filter((e=>"content"===e.matchType)),n=[]
|
|
598
599
|
t.length>0&&t.forEach((e=>{n.push(e.relativePath+" [filename match]")}))
|
|
@@ -723,15 +724,15 @@ if(r)r.sessionId!==e&&((0,m.logSessionIdentity)(n,"_meta-session-switch",{prevSe
|
|
|
723
724
|
else{const t=await(0,u.getServerUrl)(o,k)
|
|
724
725
|
h.sessionIdentity.setIdentity({providerId:"opencode",sessionId:e,serverUrl:t||""})}j={providerId:"opencode",sessionId:e,messageId:t,createdAt:(new Date).toISOString()},(0,m.logSessionIdentity)(n,"_meta",{sessionId:e,messageId:t})}else if(g=n,E=S,v||(v=!0,k.warn("No _meta.sessionId on tool call \u2014 caller not on alchemylab-opencode fork.",{tool:g,metaKeys:E?Object.keys(E):null})),!1!==P?.requiresSession)throw(0,p.createMcpProtocolError)(`_meta.sessionId required for tool '${n}'`,{tool:n})
|
|
725
726
|
h.sessionIdentity.setCurrentCallOrigin(j)
|
|
726
|
-
const
|
|
727
|
+
const x=j?.sessionId||S?.sessionId
|
|
727
728
|
if(o?.workspaceManager){q=Date.now()
|
|
728
729
|
try{const e=await(0,u.getServerUrl)(o,k)
|
|
729
|
-
e&&s&&await o.workspaceManager.ensureReadonlyBranchIfNeeded(e,n,s,
|
|
730
|
+
e&&s&&await o.workspaceManager.ensureReadonlyBranchIfNeeded(e,n,s,x)}catch(e){k.debug("Error during workspace check",{error:(0,d.getErrorMessage)(e)})}Date.now()}const R=o?{...o,currentSessionId:x??"__server__"}:null,M=`${Date.now()}-${Math.random().toString(36).slice(2,10)}`,O=e=>{const{getActionServerBaseUrl:r}=t(9414)
|
|
730
731
|
fetch(r()+"/api/mcp/tool-call-event",{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({action:e,callId:M}),signal:AbortSignal.timeout(500)}).catch((()=>{}))}
|
|
731
732
|
let $
|
|
732
733
|
O("start")
|
|
733
734
|
try{if(P){(0,y.preNormalize)(n,l),await(0,w.expandTaskRefsInArgs)(l,s,j?.sessionId,k),l=(0,f.resolveSchema)(P).parse(l)
|
|
734
|
-
const t=e.params?._meta?.progressToken,r=c?.sendNotification,o={context:
|
|
735
|
+
const t=e.params?._meta?.progressToken,r=c?.sendNotification,o={context:R,apiClient:s,logger:i,metrics:a,mcpServer:I,cliOrigin:j,progressToken:t,sendNotification:r}
|
|
735
736
|
$=await P.handler(l,o)}else k.info(`Tool ${n} not found, returning negative response`),$={content:[{type:"text",text:`The tool '${n}' does not exist.`}]}}finally{O("end")}return Date.now(),Date.now(),T({tool:n,success:!0}),$}catch(t){k.error("Error executing tool:",{error:t instanceof Error?t.stack:t+"",tool:e.params.name}),a.incrementCounter("tool_errors_total",1,{tool:e.params.name,error:t instanceof Error?t.name:"unknown"})
|
|
736
737
|
let r="Unknown error"
|
|
737
738
|
return r=t instanceof b.ZodError?function(e,t){return 1===e.issues.length?n(e.issues[0],t):e.issues.map((e=>n(e,t))).join("; ")}(t,l):(0,d.getStructuredErrorMessage)(t),{content:[{type:"text",text:"Error: "+r}],isError:!0}}var g,E})),k.info("Tools registration complete")}
|
|
@@ -1044,7 +1045,27 @@ const n=this.isOffline()
|
|
|
1044
1045
|
return t?(this.consecutiveFailures=0,this.currentBackoffMs=0,n&&this.setOfflineMode(!1)):(this.consecutiveFailures++,this.currentBackoffMs=Math.min(this.options.checkIntervalMs*Math.pow(2,this.consecutiveFailures-1),3e5),n||this.consecutiveFailures<this.options.retryCount||this.setOfflineMode(!0)),this.logger.debug("Health check complete",{isOnline:t,latency:r,consecutiveFailures:this.consecutiveFailures,currentBackoffMs:this.currentBackoffMs,statusChanged:n!==this.isOffline()}),this.lastCheckTime=Date.now(),t}catch(t){return this.logger.error("Health check failed with error",{error:(0,r.getErrorMessage)(t),elapsed:Date.now()-e}),this.metrics.incrementCounter("health_check_error",1),this.failureCount++,this.lastFailureTime=Date.now(),this.metrics.setGauge("health_check_failure_count",this.failureCount),this.metrics.setGauge("health_check_last_failure",this.lastFailureTime),this.consecutiveFailures++,this.currentBackoffMs=Math.min(this.options.checkIntervalMs*Math.pow(2,this.consecutiveFailures-1),3e5),this.isOffline()||this.consecutiveFailures<this.options.retryCount||this.setOfflineMode(!0),this.lastCheckTime=Date.now(),!1}}startHealthChecks(){this.checkInterval&&clearInterval(this.checkInterval),this.performHealthCheck().catch((()=>{})),this.checkInterval=setInterval((()=>{this.performHealthCheck().catch((()=>{}))}),this.options.checkIntervalMs),this.logger.info("Health check monitoring started",{checkIntervalMs:this.options.checkIntervalMs})}async checkConnectivity(){return await this.performHealthCheck()}stopHealthChecks(){this.checkInterval&&(clearInterval(this.checkInterval),this.checkInterval=null,this.logger.info("Health check monitoring stopped"))}async requestHealthCheck(){if(this.forcedOfflineMode)return this.logger.debug("Health check skipped - offline mode is forced"),!1
|
|
1045
1046
|
const e=this.online,t=await this.performHealthCheck()
|
|
1046
1047
|
return e!==t&&(t?(this.logger.info("Health check status changed to ONLINE"),this.options.onOnlineCallback()):(this.logger.info("Health check status changed to OFFLINE"),this.options.onOfflineCallback())),t}isOffline(){return this.forcedOfflineMode||!1}scheduleNextCheck(e=this.options.checkIntervalMs){this.checkInterval&&(clearInterval(this.checkInterval),this.checkInterval=null),0!==e?setTimeout((()=>{this.performHealthCheck().catch((()=>{}))}),e||this.options.checkIntervalMs||3e4):this.performHealthCheck().catch((()=>{}))}setOfflineMode(e){const t=this.forcedOfflineMode
|
|
1047
|
-
this.forcedOfflineMode=e,t!==e&&(this.logger.info("Offline mode "+(e?"ENABLED":"DISABLED")),this.metrics.setGauge("health_check_forced_offline",e?1:0),e||this.scheduleNextCheck(0))}getStats(){return{consecutiveFailures:this.consecutiveFailures,currentBackoffMs:this.currentBackoffMs,lastCheckTime:this.lastCheckTime}}}},
|
|
1048
|
+
this.forcedOfflineMode=e,t!==e&&(this.logger.info("Offline mode "+(e?"ENABLED":"DISABLED")),this.metrics.setGauge("health_check_forced_offline",e?1:0),e||this.scheduleNextCheck(0))}getStats(){return{consecutiveFailures:this.consecutiveFailures,currentBackoffMs:this.currentBackoffMs,lastCheckTime:this.lastCheckTime}}}},1719(e,exports,t){"use strict"
|
|
1049
|
+
Object.defineProperty(exports,"__esModule",{value:!0}),exports.handleQuestSetCriteriaStatuses=async function(e,t,o,s,i){const a=s.child({tool:"quest_set_criteria_statuses"})
|
|
1050
|
+
try{if(!t.projectId)return{content:[{type:"text",text:"\u274c No project context available."}],isError:!0}
|
|
1051
|
+
const r=o.getDocumentClient(),s=await r.getDocument(e.questId)
|
|
1052
|
+
if(!s)return{content:[{type:"text",text:"\u274c Quest not found: "+e.questId}],isError:!0}
|
|
1053
|
+
if("Quest"!==s.type)return{content:[{type:"text",text:`\u274c Document ${e.questId} is not a quest (type: ${s.type}).`}],isError:!0}
|
|
1054
|
+
const c=s.metadata||{},l=c.status||n.QUEST_STATUS_OPEN
|
|
1055
|
+
if(l!==n.QUEST_STATUS_OPEN)return{content:[{type:"text",text:`\u274c Quest status is "${l}", not "open". Criterion updates are only valid while the quest is open.`}],isError:!0}
|
|
1056
|
+
const d=Array.isArray(c.criteria)?c.criteria:[]
|
|
1057
|
+
if(0===d.length)return{content:[{type:"text",text:"\u274c Quest has no structured criteria checklist. Set metadata.criteria via plan_write update before calling this tool."}],isError:!0}
|
|
1058
|
+
const u=new Map(d.map((e=>[e.id,e]))),h=e.updates.map((e=>e.id)).filter((e=>!u.has(e)))
|
|
1059
|
+
if(h.length>0){const e=d.map((e=>`"${e.id}"`)).join(", ")
|
|
1060
|
+
return{content:[{type:"text",text:`\u274c Unknown criterion id(s): ${h.map((e=>`"${e}"`)).join(", ")}. Valid ids on this quest: ${e}.`}],isError:!0}}const p=new Map(e.updates.map((e=>[e.id,e]))),g=d.map((e=>{const t=p.get(e.id)
|
|
1061
|
+
if(!t)return e
|
|
1062
|
+
const r={...e,status:t.status}
|
|
1063
|
+
return void 0!==t.evidence&&(r.evidence=t.evidence),r})),m={...c,criteria:g}
|
|
1064
|
+
await r.updateDocument(e.questId,{metadata:m}),i.incrementCounter("quest_set_criteria_statuses_total",1,{updatedCount:e.updates.length+""})
|
|
1065
|
+
const f=s.localId||s.id,y=g.filter((e=>"verified"===e.status)).length,w=e.updates.map((e=>{const t=u.get(e.id)
|
|
1066
|
+
return`- ${e.id}: ${e.status}${e.evidence?` (evidence: ${e.evidence})`:""}${t?.description?" \u2014 "+t.description:""}`}))
|
|
1067
|
+
return a.info("quest_set_criteria_statuses processed",{questId:f,updatedCount:e.updates.length,verifiedAfter:y,totalCriteria:g.length}),{content:[{type:"text",text:`\u2705 **Criteria updated (${y}/${g.length} verified)**\n\nQuest **${f}**:\n`+w.join("\n")+(y===g.length?"\n\nAll criteria are now verified. Call quest_audit_complete when ready to flip the quest status.":"")}]}}catch(e){return a.error("quest_set_criteria_statuses failed",{error:(0,r.getErrorMessage)(e)}),{content:[{type:"text",text:"\u274c **quest_set_criteria_statuses failed:** "+(0,r.getErrorMessage)(e)}],isError:!0}}}
|
|
1068
|
+
const r=t(8824),n=t(3416)},1725(e,exports,t){"use strict"
|
|
1048
1069
|
function r(e,t,r){try{const n=`[${(new Date).toISOString()}] ${t}${r?" "+JSON.stringify(r):""}\n`,o=(0,v.join)(e.basePath||process.cwd(),".alchemy_lab","spawn-debug.log");(0,k.appendFileSync)(o,n)}catch{}}function n(e,t){return t?`Instruction code: ${t}. When you report back or ask a question via session_message_operations send, include relatesTo: "${t}" so the parent can trace this work.\n\n${e}`:e}async function o(e){const{apiClient:t,fromSessionId:r,toSessionId:n,body:o,requestId:s,logger:i}=e
|
|
1049
1070
|
if(!t||!r)return
|
|
1050
1071
|
const a=t.getSessionMessageClient()
|
|
@@ -1077,7 +1098,7 @@ if(r.length>0){const e=r.map((e=>e.opencodeSessionId)).join(", ")
|
|
|
1077
1098
|
if(!u)return s.warn("Blocked spawn: request already has active workers",{requestId:d,existingWorkerCount:r.length,existingSessionIds:r.map((e=>e.opencodeSessionId))}),{content:[{type:"text",text:`\u274c Cannot spawn: Request ${d} already has ${r.length} active worker(s): ${e}\n\nOptions:\n\u2022 Use \`useExistingSession: "${r[0].opencodeSessionId}"\` to send work to the existing session\n\u2022 Use \`allowParallel: true\` if you really need multiple workers on the same request`}],isError:!0}
|
|
1078
1099
|
E=`\u26a0\ufe0f Warning: Request ${d} already has ${r.length} active worker(s): ${e}. Proceeding anyway (allowParallel=true).\n\n`,s.warn("Spawning parallel subagent for request with existing active workers",{requestId:d,existingWorkerCount:r.length,existingSessionIds:r.map((e=>e.opencodeSessionId)),allowParallel:!0})}}}catch(e){s.debug("Failed to check for existing workers",{error:(0,I.getErrorMessage)(e)})}let T,q,P=l
|
|
1079
1100
|
d&&(T="requests/"+d,r(t,"Setting initialBranch for agent",{agent:c,requestId:d,initialBranch:T,agentRequestContextMode:p||"undefined"}),P="readonly"===p?`Working on request ${d} (READONLY mode - you cannot modify files, only explore and report).\n\n${l}`:`Working on request ${d}.\n\n${l}`)
|
|
1080
|
-
let j,
|
|
1101
|
+
let j,x=!1
|
|
1081
1102
|
if(h){if(q=h,s.info("Using existing session for spawn",{sessionId:q,requestId:d}),!g)throw new m.ValidationError("Could not determine OpenCode server URL")
|
|
1082
1103
|
try{let e
|
|
1083
1104
|
try{const t=await fetch(`http://localhost:${S}/api/project-settings`)
|
|
@@ -1086,7 +1107,7 @@ if(r.data?.defaultModel){const[t,...n]=r.data.defaultModel.split("/")
|
|
|
1086
1107
|
e={providerID:t,modelID:n.join("/")}}}}catch{}j=await o({apiClient:i,fromSessionId:a?.sessionId,toSessionId:q,body:P,requestId:d,logger:s})
|
|
1087
1108
|
const t=n(P,j),r=`${g.replace(/\/$/,"")}/session/${q}/prompt_async`,l={alchemy:{kind:"agent-delegation",payload:{body:P,fromSessionId:a?.sessionId,fromAgent:w.sessionIdentity.getIdentity()?.agentType,...d?{requestId:d}:{},...j?{instructionCode:j}:{}}}},u=await fetch(r,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({parts:[{type:"text",text:t,metadata:l}],...c?{agent:c}:{},...e?{model:e}:{}}),signal:AbortSignal.timeout(1e4)})
|
|
1088
1109
|
if(!u.ok){const e=await u.text().catch((()=>"Unknown error"))
|
|
1089
|
-
throw Error(`Failed to send to existing session: ${u.status} ${e}`)}s.info("Prompt sent to existing session",{sessionId:q,agent:c})}catch(e){throw Error("Failed to use existing session: "+(0,I.getErrorMessage)(e))}}else{
|
|
1110
|
+
throw Error(`Failed to send to existing session: ${u.status} ${e}`)}s.info("Prompt sent to existing session",{sessionId:q,agent:c})}catch(e){throw Error("Failed to use existing session: "+(0,I.getErrorMessage)(e))}}else{x=!0,r(t,"Creating session via spawn-session endpoint")
|
|
1090
1111
|
const h=v;(0,b.logSessionIdentity)("subagent_operations.spawn","_meta",{parentSessionId:h})
|
|
1091
1112
|
try{const p=`http://localhost:${S}/api/spawn-session`,g=await fetch(p,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({agent:c,prompt:l,requestId:d,parentSessionId:h,title:e.title,specialization:e.specialization,specializationHeadline:e.specializationHeadline,allowParallel:u,callerAgentType:w.sessionIdentity.getIdentity()?.agentType}),signal:AbortSignal.timeout(15e3)})
|
|
1092
1113
|
if(!g.ok){const e=await g.text().catch((()=>"Unknown error"))
|
|
@@ -1104,10 +1125,10 @@ if(e.ok){const t=(await e.json()).find((e=>"user"===e.info?.role)),i=t?.parts.fi
|
|
|
1104
1125
|
if(t&&i){const e={...i,metadata:{...i.metadata||{},alchemy:{kind:"agent-delegation",payload:n}}},c=`${s}/session/${r}/message/${t.info.id}/part/${i.id}`,l=await fetch(c,{method:"PATCH",headers:{"Content-Type":"application/json"},body:JSON.stringify(e),signal:AbortSignal.timeout(5e3)})
|
|
1105
1126
|
if(l.ok)return void o.info("Tagged initial delegation message",{sessionId:r,messageId:t.info.id,partId:i.id,attempt:a})
|
|
1106
1127
|
const d=await l.text().catch((()=>"unknown"))
|
|
1107
|
-
o.warn("PATCH initial delegation failed",{sessionId:r,status:l.status,body:d.slice(0,200)})}}}catch{}await new Promise((e=>setTimeout(e,500)))}o.warn("Timed out tagging initial delegation; message will appear as plain user bubble",{sessionId:r,attempts:a})}({serverUrl:I,sessionId:y,payload:{body:P,fromSessionId:a?.sessionId,fromAgent:w.sessionIdentity.getIdentity()?.agentType,...d?{requestId:d}:{},...j?{instructionCode:j}:{}},logger:s})}catch(e){throw Error("Failed to spawn subagent: "+(0,I.getErrorMessage)(e))}}let
|
|
1108
|
-
|
|
1128
|
+
o.warn("PATCH initial delegation failed",{sessionId:r,status:l.status,body:d.slice(0,200)})}}}catch{}await new Promise((e=>setTimeout(e,500)))}o.warn("Timed out tagging initial delegation; message will appear as plain user bubble",{sessionId:r,attempts:a})}({serverUrl:I,sessionId:y,payload:{body:P,fromSessionId:a?.sessionId,fromAgent:w.sessionIdentity.getIdentity()?.agentType,...d?{requestId:d}:{},...j?{instructionCode:j}:{}},logger:s})}catch(e){throw Error("Failed to spawn subagent: "+(0,I.getErrorMessage)(e))}}let R=E
|
|
1129
|
+
R+=h?`Prompt sent to existing session ${q}.`:`Background ${c} subagent spawned successfully.`,d&&(R+="\nWorking on: "+d),j&&(R+=`\nInstruction code: ${j} (the specialist will cite this on their reports/questions via relatesTo)`),R+="\n\nThe subagent is now working independently. You can continue with other tasks.","coder"===c&&(R+="\n\nIf this work has shifted or expanded your area of expertise, update your specialization summary with `update_specialization`.")
|
|
1109
1130
|
const M=!!q&&"unknown"!==q&&"spawning"!==q
|
|
1110
|
-
return{content:[{type:"text",text:
|
|
1131
|
+
return{content:[{type:"text",text:R}],...(0,_.alchemyMeta)({kind:"spawn-subagent",spawnedSessionId:M?q:void 0,agentType:c,requestId:d||void 0,description:e.title||l.slice(0,50)||c,...j?{instructionCode:j}:{}}),...j?{instructionCode:j}:{}}}async function i(e,t,r,s,i,a,c){const l=await(0,y.getServerUrl)(r,s)
|
|
1111
1132
|
if(!l)throw new m.ValidationError("Could not determine OpenCode server URL")
|
|
1112
1133
|
if(s.info("Sending message to subagent session",{sessionId:e,promptLength:t.length}),i)try{const t=c?.sessionId
|
|
1113
1134
|
if(t){const r=i.getCLISessionClient()
|
|
@@ -1591,10 +1612,10 @@ f.info("Initial branch context",{initialBranch:S.branch,initialRequestId:S.reque
|
|
|
1591
1612
|
const T=[]
|
|
1592
1613
|
for(const e of u){const{normalizedPath:t,fullPath:n}=l.validateAndNormalizePath(e.source,r),{normalizedPath:o,fullPath:s}=l.validateAndNormalizePath(e.destination,r)
|
|
1593
1614
|
T.push({source:t,destination:o,fullSource:n,fullDestination:s})}I=l.FileOperationPhase.TASK_VALIDATION,g.incrementCounter("move_files_phase",1,{phase:I})
|
|
1594
|
-
const q=await l.validateTaskId(E,T[0].source,n,f,g,k.metricsPrefix),P=q?.requestId,j=await l.validateWorkItemStates(E,T[0].source,n,s,r,f,g,k.metricsPrefix),
|
|
1595
|
-
|
|
1596
|
-
const
|
|
1597
|
-
if(!
|
|
1615
|
+
const q=await l.validateTaskId(E,T[0].source,n,f,g,k.metricsPrefix),P=q?.requestId,j=await l.validateWorkItemStates(E,T[0].source,n,s,r,f,g,k.metricsPrefix),x=await l.autoPromoteTaskStatus(E,q.status,P,j.request?.status,T[0].source,n,s,f,g,k.metricsPrefix)
|
|
1616
|
+
x.taskPromoted&&f.info(`Auto-promoted task ${E} (${q.title||"Untitled"}) to in_progress for file operations`,{taskId:E,taskTitle:q.title,previousStatus:q.status,newStatus:x.newTaskStatus,operationCount:u.length}),x.requestPromoted&&f.info(`Auto-promoted request ${P} to in_progress for file operations`,{requestId:P,previousStatus:j.request?.status,newStatus:x.newRequestStatus,triggeringTaskId:E})
|
|
1617
|
+
const R=await l.ensureCorrectWorkspaceContext({taskPromoted:x.taskPromoted,requestId:P,context:r,operation:"move-files",logger:f,metrics:g,metricsPrefix:k.metricsPrefix})
|
|
1618
|
+
if(!R.success)throw Error(R.error)
|
|
1598
1619
|
let M={hadUserMods:!1,userModsCommitHash:void 0}
|
|
1599
1620
|
if(r.git)try{f.debug("[MOVE-FILES] Checking for user changes before move operations")
|
|
1600
1621
|
const e=await(0,h.commitUserChangesBeforeToolOperation)(r.git,"move-files",{requestId:P,taskId:E,workspaceManager:r.workspaceManager},f,g)
|
|
@@ -1632,7 +1653,7 @@ exports.def={name:"quick_manage",description:"WHEN TO USE: trivial single-file e
|
|
|
1632
1653
|
Object.defineProperty(exports,"__esModule",{value:!0}),exports.buildTaskEndpoint=function(e,t,r){const n=r?"/"+r.replace(/^\//,""):""
|
|
1633
1654
|
return`/api/projects/${e}/tasks/${encodeURIComponent(t)}${n}`}},2462(e,exports,t){"use strict"
|
|
1634
1655
|
Object.defineProperty(exports,"__esModule",{value:!0})
|
|
1635
|
-
const r=t(2245),n=t(9080),o=t(5692),s=t(9030),i=t(2903),a=t(4607),c=t(9499),l=t(6770),d=t(8045),u=t(9697),h=t(9196),p=t(5459),g=t(4805),m=t(260),f=t(2283),y=t(4165),w=t(7834),b=t(9373),I=t(6111),k=t(700),v=t(1535),C=t(7257),_=t(9230),E=t(4150),S=t(6473),T=t(6309),q=t(4921),P=t(8850),j=t(3556),
|
|
1656
|
+
const r=t(2245),n=t(9080),o=t(5692),s=t(9030),i=t(2903),a=t(4607),c=t(9499),l=t(6770),d=t(8045),u=t(9697),h=t(9196),p=t(5459),g=t(4805),m=t(260),f=t(2283),y=t(4165),w=t(7834),b=t(9373),I=t(6111),k=t(700),v=t(1535),C=t(7257),_=t(9230),E=t(4150),S=t(6473),T=t(6309),q=t(4921),P=t(8850),j=t(3556),x=t(1391),R=t(6315),M=t(7713),O=t(6252),$=t(577),D=t(4206),A=t(213),F=t(7250),N=t(2425),z=t(1540),L=t(5767),H=t(4973),B=t(509),U=t(7613),G=t(8456),W=t(3322),V=t(5247),Q=t(8849),K=t(542);(0,r.registerTool)(n.def),(0,r.registerTool)(o.def),(0,r.registerTool)(s.def),(0,r.registerTool)(i.def),(0,r.registerTool)(a.def),(0,r.registerTool)(c.def),(0,r.registerTool)(l.def),(0,r.registerTool)(d.def),(0,r.registerTool)(u.def),(0,r.registerTool)(h.def),(0,r.registerTool)(p.def),(0,r.registerTool)(g.def),(0,r.registerTool)(m.def),(0,r.registerTool)(f.def),(0,r.registerTool)(y.def),(0,r.registerTool)(w.def),(0,r.registerTool)(b.def),(0,r.registerTool)(I.def),(0,r.registerTool)(k.def),(0,r.registerTool)(v.def),(0,r.registerTool)(E.def),(0,r.registerTool)(C.def),(0,r.registerTool)(_.def),(0,r.registerTool)(S.def),(0,r.registerTool)(T.def),(0,r.registerTool)(q.def),(0,r.registerTool)(P.def),(0,r.registerTool)(j.def),(0,r.registerTool)(x.def),(0,r.registerTool)(R.def),(0,r.registerTool)(M.def),(0,r.registerTool)(O.def),(0,r.registerTool)($.def),(0,r.registerTool)(D.def),(0,r.registerTool)(A.def),(0,r.registerTool)(F.def),(0,r.registerTool)(N.def),(0,r.registerTool)(z.def),(0,r.registerTool)(L.def),(0,r.registerTool)(H.def),(0,r.registerTool)(B.def),(0,r.registerTool)(U.def),(0,r.registerTool)(G.def),(0,r.registerTools)(W.metaDefs),(0,r.registerTools)(V.testingDefs),(0,r.registerTools)(Q.checkingDefs),(0,r.registerTools)(K.debugDefs),(0,t(2245).freezeRegistry)()},2478(e,exports){"use strict"
|
|
1636
1657
|
Object.defineProperty(exports,"__esModule",{value:!0}),exports.requestConfig=void 0,exports.areTestsRequiredForCompletion=function(){return exports.requestConfig.requireTestsForCompletion},exports.setTestsRequiredForCompletion=function(e){exports.requestConfig.requireTestsForCompletion=e},exports.getCompletionMode=function(e){return e&&["auto-merge","ask-me","test-by-default","always-test"].includes(e)?e:"test-by-default"},exports.getReviewMode=function(e){return e&&["auto-finalize","manual-review"].includes(e)?e:"auto-finalize"},exports.getApprovalMode=function(e){return e&&["none","require-approval"].includes(e)?e:"none"},exports.requestConfig={requireTestsForCompletion:!1}},2537(e,exports,t){"use strict"
|
|
1637
1658
|
async function r(e,t,r){if(v.has(r)&&C>=t){if(0===t)return 0
|
|
1638
1659
|
try{return(await y.default.readFile(e,"utf-8")).split("\n").length}catch{return}}}function n(e,t,r){const n="depth"in e,o=n?e:r,s=n?e.isDirectory:e.isDirectory(),a=e.name,c=s?"[\u{1f4c1} DIR]":"[\u{1f4c4} FILE]"
|
|
@@ -2186,50 +2207,50 @@ const{taskId:q}=T
|
|
|
2186
2207
|
if(y.info("Replacing strings across files and documents",{taskId:q,operationCount:_.length,comment:E}),!_||0===_.length)throw new u.ValidationError("At least one operation is required")
|
|
2187
2208
|
const P=_.filter((e=>e.path)),j=_.filter((e=>e.documentId))
|
|
2188
2209
|
y.info("Operation breakdown",{fileOperations:P.length,documentOperations:j.length})
|
|
2189
|
-
const
|
|
2210
|
+
const x=[]
|
|
2190
2211
|
for(const e of P){const{normalizedPath:t,fullPath:n}=d.validateAndNormalizePath(e.path,r)
|
|
2191
|
-
|
|
2212
|
+
x.push({type:"file",path:t,fullPath:n,replacements:e.replacements,mode:e.mode||"unique"})}const R=[]
|
|
2192
2213
|
if(j.length>0&&!r.documentFileManager)throw Error("Document file manager not available - cannot process document operations")
|
|
2193
|
-
for(const e of j)
|
|
2194
|
-
if(
|
|
2214
|
+
for(const e of j)R.push({type:"document",documentId:e.documentId,replacements:e.replacements,mode:e.mode||"unique"})
|
|
2215
|
+
if(R.length>0&&r.apiClient){const e=R.map((e=>e.documentId))
|
|
2195
2216
|
try{await(0,g.ensureDocumentsNotLocked)(e,r.apiClient,y,c,"replace-strings-documents")}catch(e){if(e instanceof u.ValidationError)return{content:[{type:"text",text:e.message}],isError:!0}
|
|
2196
2217
|
throw e}}k=d.FileOperationPhase.TASK_VALIDATION,c.incrementCounter("replace_strings_phase",1,{phase:k})
|
|
2197
|
-
const M=
|
|
2218
|
+
const M=x.length>0?x[0].path:"document-operation",O=await d.validateTaskId(q,M,o,y,c,v.metricsPrefix),$=O?.requestId
|
|
2198
2219
|
let D=null
|
|
2199
|
-
|
|
2220
|
+
x.length>0&&$&&(D=await d.validateWorkItemStates(q,x[0].path,o,i,r,y,c,v.metricsPrefix))
|
|
2200
2221
|
let A={taskPromoted:!1,requestPromoted:!1}
|
|
2201
|
-
|
|
2222
|
+
x.length>0&&$&&D&&(A=await d.autoPromoteTaskStatus(q,O.status,$,D.request?.status,x[0].path,o,i,y,c,v.metricsPrefix),A.taskPromoted&&y.info("Auto-promoted task to in_progress for replace-strings operation",{taskId:q,requestId:$,previousStatus:O.status,newStatus:A.newTaskStatus,triggeringOperation:"replace-strings"}))
|
|
2202
2223
|
const F=await d.ensureCorrectWorkspaceContext({taskPromoted:A.taskPromoted,requestId:$,context:r,operation:"replace-strings",logger:y,metrics:c,metricsPrefix:v.metricsPrefix})
|
|
2203
2224
|
if(!F.success)throw Error(F.error)
|
|
2204
|
-
if(
|
|
2205
|
-
for(let e=0;e<
|
|
2206
|
-
|
|
2225
|
+
if(x.length>0){y.debug("Re-validating file paths with correct workspace context",{operationCount:x.length,workspaceBasePath:r.workspaceManager?.getCurrentContext(r.currentSessionId).basePath})
|
|
2226
|
+
for(let e=0;e<x.length;e++){const t=x[e],n=P[e],{normalizedPath:o,fullPath:s}=d.validateAndNormalizePath(n.path,r)
|
|
2227
|
+
x[e]={...t,path:o,fullPath:s}}}if(R.length>0&&$)try{await(0,h.validateRequestStatusForDocumentOperation)($,i,y,c,"replace-strings-document")}catch(e){if(e instanceof u.ValidationError)return{content:[{type:"text",text:e.message}],isError:!0}
|
|
2207
2228
|
throw e}k=d.FileOperationPhase.RECORD_CREATION,c.incrementCounter("replace_strings_phase",1,{phase:k})
|
|
2208
|
-
const N=[...
|
|
2209
|
-
if(b=z,I=z,k=v.fileOperationPhase,c.incrementCounter("replace_strings_phase",1,{phase:k}),
|
|
2229
|
+
const N=[...x.map((e=>({type:"file",path:e.path,replacements:e.replacements,mode:e.mode}))),...R.map((e=>({type:"document",documentId:e.documentId,replacements:e.replacements,mode:e.mode})))],{toolRecordId:z}=await d.createFileOperationRecords(q,$,r.projectId,v.recordType,M,{operationCount:_.length,fileOperations:x.length,documentOperations:R.length,operations:N,userComment:E},o,s,y,c,v.metricsPrefix,f)
|
|
2230
|
+
if(b=z,I=z,k=v.fileOperationPhase,c.incrementCounter("replace_strings_phase",1,{phase:k}),x.length>0&&r.git)try{y.debug("[REPLACE-STRINGS] Checking for user changes before replace operations")
|
|
2210
2231
|
const e=await(0,p.commitUserChangesBeforeToolOperation)(r.git,"replace-strings",{requestId:$,taskId:q,workspaceManager:r.workspaceManager},y,c)
|
|
2211
|
-
e.userChangesCommitted&&(y.debug("[REPLACE-STRINGS] User changes committed before replace operations",{commitHash:e.commitHash?.substring(0,8),filesCommitted:e.filesCommitted}),y.info("User changes committed before replace-strings operation",{taskId:q,fileOperationsCount:
|
|
2232
|
+
e.userChangesCommitted&&(y.debug("[REPLACE-STRINGS] User changes committed before replace operations",{commitHash:e.commitHash?.substring(0,8),filesCommitted:e.filesCommitted}),y.info("User changes committed before replace-strings operation",{taskId:q,fileOperationsCount:x.length,userCommitHash:e.commitHash?.substring(0,8),userFilesCommitted:e.filesCommitted}))}catch(e){y.debug("[REPLACE-STRINGS] Pre-tool commit failed, continuing with replacements",{error:e instanceof Error?e.message:e+""}),y.warn("Pre-tool user changes commit failed, continuing with replace operation",{taskId:q,fileOperationsCount:x.length,error:e instanceof Error?e.message:e+""})}y.debug("[REPLACE-STRINGS] Proceeding with file operations",{fileCount:x.length})
|
|
2212
2233
|
const L=[]
|
|
2213
2234
|
let H=0,B=0
|
|
2214
|
-
for(const e of
|
|
2235
|
+
for(const e of x){const t={type:"file",path:e.path,success:!1,replacements:[],successfulReplacements:0,failedReplacements:0}
|
|
2215
2236
|
try{if(await l.default.access(e.fullPath),!(await l.default.stat(e.fullPath)).isFile())throw Error("Path is not a file: "+e.path)
|
|
2216
2237
|
const r=await l.default.readFile(e.fullPath,"utf8"),{newContent:o,results:s}=await n(r,e.replacements,e.mode)
|
|
2217
|
-
t.replacements=s,t.successfulReplacements=s.filter((e=>e.success)).length,t.failedReplacements=s.filter((e=>!e.success)).length,o!==r?(await l.default.writeFile(e.fullPath,o,"utf8"),t.success=!0,B++,y.info("File updated successfully",{path:e.path,successfulReplacements:t.successfulReplacements,failedReplacements:t.failedReplacements})):0===t.failedReplacements&&(t.success=!0),H+=t.failedReplacements}catch(r){t.error=(0,m.getErrorMessage)(r),t.failedReplacements=e.replacements.length,H+=t.failedReplacements,y.error("File operation failed",{path:e.path,error:t.error})}L.push(t)}for(const e of
|
|
2238
|
+
t.replacements=s,t.successfulReplacements=s.filter((e=>e.success)).length,t.failedReplacements=s.filter((e=>!e.success)).length,o!==r?(await l.default.writeFile(e.fullPath,o,"utf8"),t.success=!0,B++,y.info("File updated successfully",{path:e.path,successfulReplacements:t.successfulReplacements,failedReplacements:t.failedReplacements})):0===t.failedReplacements&&(t.success=!0),H+=t.failedReplacements}catch(r){t.error=(0,m.getErrorMessage)(r),t.failedReplacements=e.replacements.length,H+=t.failedReplacements,y.error("File operation failed",{path:e.path,error:t.error})}L.push(t)}for(const e of R){const t={type:"document",documentId:e.documentId,success:!1,replacements:[],successfulReplacements:0,failedReplacements:0}
|
|
2218
2239
|
try{const o=await r.documentFileManager.getDocumentAsFile(e.documentId),s=r.documentFileManager.getCachedDocumentInfo(e.documentId)
|
|
2219
2240
|
t.filename=s?.filename
|
|
2220
2241
|
const i=await l.default.readFile(o,"utf8"),{newContent:a,results:c}=await n(i,e.replacements,e.mode)
|
|
2221
|
-
t.replacements=c,t.successfulReplacements=c.filter((e=>e.success)).length,t.failedReplacements=c.filter((e=>!e.success)).length,a!==i?(await l.default.writeFile(o,a,"utf8"),r.documentFileManager.markForSync(e.documentId),t.success=!0,B++,y.info("Document updated successfully",{documentId:e.documentId,filename:t.filename,successfulReplacements:t.successfulReplacements,failedReplacements:t.failedReplacements})):0===t.failedReplacements&&(t.success=!0),H+=t.failedReplacements}catch(r){t.error=(0,m.getErrorMessage)(r),t.failedReplacements=e.replacements.length,H+=t.failedReplacements,y.error("Document operation failed",{documentId:e.documentId,error:t.error})}L.push(t)}if(
|
|
2222
|
-
t?.success&&await r.documentFileManager.syncDocument(e.documentId)}}catch(e){y.warn("Some documents may not have synced properly",{error:e})}const U=await d.handleMultiFileGitCommit(q,
|
|
2223
|
-
try{await s.updateToolRecord(I,{metadata:{path:
|
|
2242
|
+
t.replacements=c,t.successfulReplacements=c.filter((e=>e.success)).length,t.failedReplacements=c.filter((e=>!e.success)).length,a!==i?(await l.default.writeFile(o,a,"utf8"),r.documentFileManager.markForSync(e.documentId),t.success=!0,B++,y.info("Document updated successfully",{documentId:e.documentId,filename:t.filename,successfulReplacements:t.successfulReplacements,failedReplacements:t.failedReplacements})):0===t.failedReplacements&&(t.success=!0),H+=t.failedReplacements}catch(r){t.error=(0,m.getErrorMessage)(r),t.failedReplacements=e.replacements.length,H+=t.failedReplacements,y.error("Document operation failed",{documentId:e.documentId,error:t.error})}L.push(t)}if(R.length>0)try{for(const e of R){const t=L.find((t=>t.documentId===e.documentId))
|
|
2243
|
+
t?.success&&await r.documentFileManager.syncDocument(e.documentId)}}catch(e){y.warn("Some documents may not have synced properly",{error:e})}const U=await d.handleMultiFileGitCommit(q,x,L,B,{operationType:"Replace strings",toolRecordId:I,successField:"successfulReplacements",logger:y,metrics:c,metricsPrefix:"replace_strings"},r),G=d.processMultiFileOperationResults(L,"successfulReplacements"),{successfulOperations:W,failedOperations:V,totalSuccessfulChanges:Q,overallSuccess:K,successfulFiles:J,failedFiles:Y}=G
|
|
2244
|
+
try{await s.updateToolRecord(I,{metadata:{path:x.length>0?x[0].path:"document:"+R[0]?.documentId,status:K?"completed":"failed",error:K?void 0:V+" operations failed",totalOperations:L.length,successfulFiles:J,failedFiles:Y,operations:N,totalSuccessfulReplacements:Q,totalFailedReplacements:H,operationsWithChanges:B,processingTime:Date.now()-w,userComment:E,...x.length>0&&U.success&&U.commitHash&&{commitHash:U.commitHash,previousCommitHash:U.previousCommitHash||void 0}},note:K?`String replacement completed: ${W}/${L.length} operations successful${x.length>0?" (committed to git)":""}`:`String replacement partially failed: ${V}/${L.length} operations failed`})}catch(e){y.warn("Failed to update tool record",{recordError:e})}d.formatMultiFileToolResponse("String Replacement",{successfulOperations:W,failedOperations:V,totalSuccessfulChanges:Q,overallSuccess:K,successfulFiles:J,failedFiles:Y},U,F)
|
|
2224
2245
|
let Z="## String Replacement Results\n\n"
|
|
2225
2246
|
if(r.workspaceManager){const e=r.workspaceManager.getCurrentContext(r.currentSessionId)
|
|
2226
|
-
e.permanentBranch||(Z+=`**Branch:** \`${e.branchName}\`\n\n`)}if(Z+="**Summary:**\n",Z+=`- **Files processed:** ${W+V}\n`,Z+=`- **Successful operations:** ${W}\n`,Z+=`- **Failed operations:** ${V}\n`,Z+=`- **Total replacements:** ${
|
|
2247
|
+
e.permanentBranch||(Z+=`**Branch:** \`${e.branchName}\`\n\n`)}if(Z+="**Summary:**\n",Z+=`- **Files processed:** ${W+V}\n`,Z+=`- **Successful operations:** ${W}\n`,Z+=`- **Failed operations:** ${V}\n`,Z+=`- **Total replacements:** ${Q} successful, ${H} failed\n\n`,U.success&&U.commitHash&&(Z+="**Git Commit:**\n",Z+=`- **Commit Hash:** ${U.commitHash.substring(0,8)}\n`,Z+=`- **Files Committed:** ${U.filesCommitted.length}\n`,U.previousCommitHash&&(Z+=`- **Previous Commit:** ${U.previousCommitHash.substring(0,8)}\n`),Z+="\n"),1===L.length){const e=L[0]
|
|
2227
2248
|
if(Z+=`**Operation:** ${e.success?"\u2705 Success":"\u274c Failed"}\n`,"file"===e.type?Z+=`**File:** ${e.path}\n`:(Z+="**Document:** "+e.documentId,e.filename&&(Z+=` (${e.filename})`),Z+="\n"),e.error?Z+=`**Error:** ${e.error}\n`:(Z+=`**Replacements:** ${e.successfulReplacements} successful`,e.failedReplacements>0&&(Z+=`, ${e.failedReplacements} failed`),Z+="\n"),e.replacements.some((e=>!e.success))){Z+="**Failed Replacement Details:**\n"
|
|
2228
|
-
for(const t of e.replacements.filter((e=>!e.success)))Z+=`- "${t.old_str}" \u2192 "${t.new_str}": ${t.error}\n`}}else{Z+="**Summary:**\n",Z+=`- **Total Operations:** ${L.length}\n`,Z+=`- **Successful:** ${W}\n`,Z+=`- **Failed:** ${V}\n`,Z+=`- **Total Replacements:** ${
|
|
2249
|
+
for(const t of e.replacements.filter((e=>!e.success)))Z+=`- "${t.old_str}" \u2192 "${t.new_str}": ${t.error}\n`}}else{Z+="**Summary:**\n",Z+=`- **Total Operations:** ${L.length}\n`,Z+=`- **Successful:** ${W}\n`,Z+=`- **Failed:** ${V}\n`,Z+=`- **Total Replacements:** ${Q} successful, ${H} failed\n\n`,Z+="**Detailed Results:**\n\n"
|
|
2229
2250
|
for(const e of L){if("file"===e.type?Z+=`### File: ${e.path}\n`:(Z+="### Document: "+e.documentId,e.filename&&(Z+=` (${e.filename})`),Z+="\n"),Z+=`- **Status:** ${e.success?"\u2705 Success":"\u274c Failed"}\n`,e.error?Z+=`- **Error:** ${e.error}\n`:(Z+=`- **Replacements:** ${e.successfulReplacements} successful`,e.failedReplacements>0&&(Z+=`, ${e.failedReplacements} failed`),Z+="\n"),e.replacements.some((e=>!e.success))){Z+="- **Failed Replacement Details:**\n"
|
|
2230
|
-
for(const t of e.replacements.filter((e=>!e.success)))Z+=` - "${t.old_str}" \u2192 "${t.new_str}": ${t.error}\n`}Z+="\n"}}
|
|
2251
|
+
for(const t of e.replacements.filter((e=>!e.success)))Z+=` - "${t.old_str}" \u2192 "${t.new_str}": ${t.error}\n`}Z+="\n"}}R.length>0&&(Z+="\u{1f4c4} **Document Changes:** Modified documents have been automatically synced back to the tracking system.\n\n")
|
|
2231
2252
|
const X=Date.now()-w
|
|
2232
|
-
return y.info("Replace strings operation completed",{duration:X,success:
|
|
2253
|
+
return y.info("Replace strings operation completed",{duration:X,success:K,totalOperations:L.length,successfulOperations:W,failedOperations:V}),c.incrementCounter("replace_strings_total",1,{success:K}),{content:[{type:"text",text:Z}],isError:!K}}catch(t){const r=Date.now()-w
|
|
2233
2254
|
if(y.error("Replace strings operation failed",{error:t instanceof Error?t.stack:t+"",duration:r,phase:k}),I)try{await s.updateToolRecord(I,{metadata:{path:e?.operations?.[0]?.path||e?.operations?.[0]?.documentId,status:"failed",error:(0,m.getErrorMessage)(t),phase:k,duration:r,userComment:e?.comment},note:"String replacement failed: "+(0,m.getErrorMessage)(t)})}catch(e){}return c.incrementCounter("replace_strings_errors",1,{phase:k}),{content:[{type:"text",text:"\u274c **Replace Strings Failed:** "+(0,m.getErrorMessage)(t)}],isError:!0}}}
|
|
2234
2255
|
const l=c(t(1943)),d=a(t(5967)),u=t(9860),h=t(5003),p=t(7478),g=t(9949),m=t(8824)},3322(e,exports,t){"use strict"
|
|
2235
2256
|
var r,n=this&&this.__createBinding||(Object.create?function(e,t,r,n){void 0===n&&(n=r)
|
|
@@ -2273,7 +2294,7 @@ var m=t(6539)
|
|
|
2273
2294
|
Object.defineProperty(exports,"ClientFactory",{enumerable:!0,get(){return m.ClientFactory}})
|
|
2274
2295
|
const f=t(6539)
|
|
2275
2296
|
exports.default={ClientFactory:f.ClientFactory}},3416(e,exports){"use strict"
|
|
2276
|
-
Object.defineProperty(exports,"__esModule",{value:!0}),exports.
|
|
2297
|
+
Object.defineProperty(exports,"__esModule",{value:!0}),exports.QUEST_METADATA_KEYS=exports.QUEST_COMPLETION_MODE_DEFAULT=exports.QUEST_COMPLETION_MODES=exports.QUEST_STATUSES=exports.QUEST_STATUS_DRAFT=exports.QUEST_STATUS_CLOSED=exports.QUEST_STATUS_PENDING_REVIEW=exports.QUEST_STATUS_OPEN=exports.QUEST_DEFAULTS=void 0,exports.defaultMinIterations=function(e){return"auto-close"===e?3:1},exports.QUEST_DEFAULTS={tickIntervalSeconds:1800,maxInFlight:1,maxPerDay:24,minIterations:3,consecutiveDoneAudits:0},exports.QUEST_STATUS_OPEN="open",exports.QUEST_STATUS_PENDING_REVIEW="pending_review",exports.QUEST_STATUS_CLOSED="closed",exports.QUEST_STATUS_DRAFT="draft",exports.QUEST_STATUSES=[exports.QUEST_STATUS_DRAFT,exports.QUEST_STATUS_OPEN,exports.QUEST_STATUS_PENDING_REVIEW,exports.QUEST_STATUS_CLOSED],exports.QUEST_COMPLETION_MODES=["auto-close","audit-then-pending"],exports.QUEST_COMPLETION_MODE_DEFAULT="audit-then-pending",exports.QUEST_METADATA_KEYS=["criteria","tickIntervalSeconds","maxInFlight","maxPerDay","minIterations","status","completionMode"]},3420(e,exports,t){"use strict"
|
|
2277
2298
|
Object.defineProperty(exports,"__esModule",{value:!0}),exports.handleGetTaskInformation=async function(e,t,i,a,c){const l=a.child({tool:"get_task_information"})
|
|
2278
2299
|
l.info("Getting task information",{args:e})
|
|
2279
2300
|
const d=c.startTimer("tool_handler_duration")
|
|
@@ -2482,11 +2503,11 @@ try{await b.updateTaskStatus(P,"canceled"),f.info("Canceled task after operation
|
|
|
2482
2503
|
j?f.warn("File operation completed with partial failures",{requestId:q}):f.info("File operation completed successfully"),f.debug("Completing task")
|
|
2483
2504
|
try{await(0,a.handleCompleteTask)({taskId:P,summary:`Executed ${t} operation for quick fix: ${v}${j?" (partial success)":""}`},u,h,p,g),f.info("Task completed successfully",{taskId:P})}catch(e){f.error("Task completion via handleCompleteTask failed, attempting direct status update",{taskId:P,error:e instanceof Error?e.message:e+"",errorStack:e instanceof Error?e.stack:void 0})
|
|
2484
2505
|
try{await b.updateTaskStatus(P,"completed"),f.info("Task completed via direct updateTaskStatus call",{taskId:P})}catch(e){return f.error("Direct task completion ALSO failed - task may be stuck in in_progress",{taskId:P,error:e instanceof Error?e.message:e+"",errorStack:e instanceof Error?e.stack:void 0,operationType:t,isDocumentOperation:!!_.documentId}),{content:[{type:"text",text:`\u26a0\ufe0f Quick change operation succeeded but task completion failed.\n\n**Request:** ${q}\n**Task:** ${P}\n**Issue:** Could not mark task as completed - it remains in 'in_progress' state\n\nThe ${t} operation was successful, but we couldn't automatically complete the task. Please use the complete-task tool manually with taskId: ${P}\n\nError: `+(e instanceof Error?e.message:e+"")}],isError:!0}}}f.debug("Completing request")
|
|
2485
|
-
const
|
|
2506
|
+
const x=j?`Quick change completed with partial success: ${v}. Some replacements failed - see details below.`:"Quick change completed: "+v,R=j?t+" operation partially completed - some operations succeeded, some failed":t+" operation executed successfully"
|
|
2486
2507
|
let M=!1
|
|
2487
|
-
try{const e=await(0,c.handleCompleteRequest)({requestId:q,summary:
|
|
2508
|
+
try{const e=await(0,c.handleCompleteRequest)({requestId:q,summary:x,acceptanceEvidence:[{evidence:R}],testVerification:void 0},u,h,p,g,m)
|
|
2488
2509
|
if(e.isError)f.error("Request completion failed, attempting direct completion",{requestId:q,error:e.content[0].text})
|
|
2489
|
-
else{try{await w.updateRequest(q,{status:"completed",completionSummary:
|
|
2510
|
+
else{try{await w.updateRequest(q,{status:"completed",completionSummary:x}),f.info("Request finalized to completed",{requestId:q})}catch(e){f.warn("Failed to finalize request to completed, may be stuck at ready_for_merge",{requestId:q,error:(0,d.getErrorMessage)(e)})}M=!0,f.info("Request completed successfully",{requestId:q})}}catch(e){f.error("Request completion threw exception, attempting direct completion",{requestId:q,error:e instanceof Error?e.message:e+""})}if(!M)try{f.info("Attempting direct request completion via API",{requestId:q}),await w.updateRequest(q,{status:"completed",completionSummary:x}),M=!0,f.info("Request completed successfully via direct API call",{requestId:q})}catch(e){return f.error("Direct request completion also failed",{requestId:q,error:e instanceof Error?e.message:e+""}),{content:[{type:"text",text:`\u26a0\ufe0f Quick change operation succeeded but request completion failed.\n\n**Request:** ${q}\n**Status:** Still in 'in_progress' - please complete manually\n\nThe file operation was successful, but we couldn't automatically complete the request. Please use the complete-request tool manually.`}],isError:!0}}const O=Date.now()-y
|
|
2490
2511
|
f.info("Quick fix completed",{requestId:q,duration:O,hasPartialFailure:j})
|
|
2491
2512
|
const $=(0,n.readAlchemyMeta)(C)?.toolRecordId
|
|
2492
2513
|
let D
|
|
@@ -2580,9 +2601,9 @@ const E={toolName:"write_file",operationName:"write",fileOperationPhase:d.FileOp
|
|
|
2580
2601
|
try{const n=e
|
|
2581
2602
|
let{path:m,documentId:S,content:T,format:q,append:P,comment:j}=n
|
|
2582
2603
|
Array.isArray(T)&&(T=T.join("\n"))
|
|
2583
|
-
const{enforceActiveTask:
|
|
2584
|
-
if("errorResult"in
|
|
2585
|
-
const{taskId:M}=
|
|
2604
|
+
const{enforceActiveTask:x}=await Promise.resolve().then(t.bind(t,3451)),R=await x(r,o,f,e.taskId)
|
|
2605
|
+
if("errorResult"in R)return R.errorResult
|
|
2606
|
+
const{taskId:M}=R,O=!!S,$=!!m
|
|
2586
2607
|
b.info("Writing content to "+(O?"document":"file"),{taskId:M,filePath:$?m:void 0,documentId:O?S:void 0,contentLength:"string"==typeof T?T.length:JSON.stringify(T).length,format:q,append:P,comment:j})
|
|
2587
2608
|
let D,A,F,N="",z=!1,L=!1
|
|
2588
2609
|
const H=$?m:void 0
|
|
@@ -2596,21 +2617,21 @@ let W=null
|
|
|
2596
2617
|
$&&G&&(W=await d.validateWorkItemStates(M,B,o,i,r,b,y,E.metricsPrefix))
|
|
2597
2618
|
let V={taskPromoted:!1,requestPromoted:!1}
|
|
2598
2619
|
$&&G&&W&&(V=await d.autoPromoteTaskStatus(M,U.status,G,W.request?.status,B,o,i,b,y,E.metricsPrefix),V.taskPromoted&&b.info("Auto-promoted task to in_progress for file operation",{taskId:M,requestId:G,previousStatus:U.status,newStatus:V.newTaskStatus,triggeringOperation:"write_file"}))
|
|
2599
|
-
const
|
|
2600
|
-
if(!
|
|
2601
|
-
if(
|
|
2620
|
+
const Q=await d.ensureCorrectWorkspaceContext({taskPromoted:V.taskPromoted,requestId:G,context:r,operation:"write_file",logger:b,metrics:y,metricsPrefix:E.metricsPrefix,requireRequestContext:$})
|
|
2621
|
+
if(!Q.success)throw Error(Q.error)
|
|
2622
|
+
if(Q.switched&&b.info("Workspace context successfully established",{requestId:G,branchName:Q.branchName,operation:"write_file"}),$&&H){const e=d.validateAndNormalizePath(H,r)
|
|
2602
2623
|
D=e.normalizedPath,A=e.fullPath,N=A
|
|
2603
2624
|
try{await c.default.access(A),L=!0}catch{L=!1,z=!0}b.debug("Path validated with correct workspace context",{rawPath:H,normalizedPath:D,fullPath:A,workspaceBasePath:r.workspaceManager?.getCurrentContext(r.currentSessionId).basePath})}if(O&&G)try{await(0,h.validateRequestStatusForDocumentOperation)(G,i,b,y,"write_file-document")}catch(e){if(e instanceof u.ValidationError)return{content:[{type:"text",text:e.message}],isError:!0}
|
|
2604
2625
|
throw e}_=d.FileOperationPhase.RECORD_CREATION,y.incrementCounter("write_file_phase",1,{phase:_})
|
|
2605
|
-
const{toolRecordId:
|
|
2606
|
-
let
|
|
2607
|
-
if(v=
|
|
2608
|
-
else
|
|
2609
|
-
let Y=
|
|
2626
|
+
const{toolRecordId:K}=await d.createFileOperationRecords(M,G,r.projectId,E.recordType,B,{operationType:O?"document":"file",documentId:O?S:void 0,documentFilename:F,filePath:$?D:void 0,contentLength:"string"==typeof T?T.length:JSON.stringify(T).length,format:q||"text",append:P||!1,wasFileCreated:!L,userComment:j},o,s,b,y,E.metricsPrefix,w)
|
|
2627
|
+
let J
|
|
2628
|
+
if(v=K,C=K,_=E.fileOperationPhase,y.incrementCounter("write_file_phase",1,{phase:_}),"json"===q)if("string"==typeof T)try{JSON.parse(T),J=T}catch(e){throw new u.ValidationError("Content is not valid JSON")}else J=JSON.stringify(T,null,2)
|
|
2629
|
+
else J="string"==typeof T?T:JSON.stringify(T,null,2)
|
|
2630
|
+
let Y=J
|
|
2610
2631
|
if($&&r.git)try{b.debug("[WRITE-FILE] Checking for user changes before write operation")
|
|
2611
2632
|
const e=await(0,p.commitUserChangesBeforeToolOperation)(r.git,"write_file",{requestId:r.workspaceManager?.getCurrentContext(r.currentSessionId)?.requestId,taskId:M},b,y)
|
|
2612
2633
|
e.userChangesCommitted&&(b.debug("[WRITE-FILE] User changes committed before write operation",{commitHash:e.commitHash?.substring(0,8),filesCommitted:e.filesCommitted}),b.info("User changes committed before write-file operation",{taskId:M,path:D,userCommitHash:e.commitHash?.substring(0,8),userFilesCommitted:e.filesCommitted}))}catch(e){b.debug("[WRITE-FILE] Pre-tool commit failed, continuing with write",{error:e instanceof Error?e.message:e+""}),b.warn("Pre-tool user changes commit failed, continuing with write operation",{taskId:M,path:D,error:e instanceof Error?e.message:e+""})}if(!N)throw Error("Target path not properly initialized")
|
|
2613
|
-
if(b.debug("[WRITE-FILE] Proceeding with file write operation",{targetPath:N}),P&&L)try{Y=await c.default.readFile(N,"utf8")+
|
|
2634
|
+
if(b.debug("[WRITE-FILE] Proceeding with file write operation",{targetPath:N}),P&&L)try{Y=await c.default.readFile(N,"utf8")+J}catch(e){b.warn("Failed to read existing content for append",{error:e})}const Z=a.default.dirname(N)
|
|
2614
2635
|
if(await c.default.mkdir(Z,{recursive:!0}),await c.default.writeFile(N,Y,"utf8"),b.info("Content written successfully",{path:$?D:"document:"+S,finalLength:Y.length,append:P,wasCreated:z}),O){r.documentFileManager.markForSync(S)
|
|
2615
2636
|
try{await r.documentFileManager.syncDocument(S),b.info("Document synced successfully",{documentId:S})}catch(e){b.warn("Failed to sync document immediately",{documentId:S,error:e})}}let X,ee,te=null,re=!1
|
|
2616
2637
|
if($){if(_=d.FileOperationPhase.GIT_COMMIT,y.incrementCounter("write_file_phase",1,{phase:_}),r.workspaceManager){const e=r.workspaceManager.getCurrentContext(r.currentSessionId)
|
|
@@ -2630,7 +2651,7 @@ const r=t(1569),n=t(3247)
|
|
|
2630
2651
|
exports.TasksSchema=r.z.object({operation:r.z.enum(["create","done","list","current","start"]).describe("Operation to perform:\n\u2022 create - Create a new task (auto-starts if no other task is in_progress)\n\u2022 done - Complete the active (in_progress) task with a summary; auto-starts the next pending task\n\u2022 current - Show only the active (in_progress) task\n\u2022 start - Switch which task is active (pauses any currently in_progress task back to pending)\n\u2022 list - List all tasks for the current request"),title:r.z.string().optional().describe("Task title (required for create)"),description:r.z.string().optional().describe("Task description (required for create)"),summary:r.z.string().optional().describe("Completion summary (required for done)"),taskId:r.z.string().optional().describe("Task to start (required for start). Accepts short forms #01 / 01 / 1 or canonical req######+#NN.")}),exports.def={name:"tasks",description:"Manage tasks within your current request.\n\n\u2022 create { title, description } \u2014 creates a task. First task auto-starts.\n\u2022 done { summary } \u2014 completes the active task. Next pending task auto-starts.\n\u2022 current \u2014 shows just the active task (the one your file edits will attach to).\n\u2022 start { taskId } \u2014 switch which pending task is active. Pauses the current active task.\n\u2022 list \u2014 shows all tasks and their status.\n\nNo requestId needed \u2014 resolved automatically from your session. taskId only required for start (accepts short forms like #01 / 01 / 1).",schema:exports.TasksSchema,annotations:{title:"Tasks",readOnlyHint:!1,destructiveHint:!1,idempotentHint:!1},handler(e,t){return(0,n.handleTasks)(e,t.context,t.apiClient,t.logger,t.metrics,t.cliOrigin)}}},4165(e,exports,t){"use strict"
|
|
2631
2652
|
Object.defineProperty(exports,"__esModule",{value:!0}),exports.def=void 0
|
|
2632
2653
|
const r=t(6183),n=t(4648)
|
|
2633
|
-
exports.def={name:"request_operations",description:"Perform operations on existing requests.\n\nOperations:\n\u2022 complete - Begin completion: provide summary, get criteria keys for verification\n\u2022 verify-criteria - Verify acceptance criteria with evidence per key (triggers merge when all verified)\n\u2022 finalize - Approve and merge a request that is ready for review\n\u2022 approve - Approve a pending request so work can begin\n\u2022 revert - Completely revert a completed request, undoing all changes\n\u2022 get-info - Get comprehensive request information\n\u2022 list - List and filter requests\n\u2022 delete-empty - Delete a request that has no tasks (safe cleanup for mistaken or obsolete requests)\n\nCompletion is two-phase: first call complete with a summary, then call verify-criteria with evidence for each criterion key.\n\nNote: To create a new request, use the separate create-request tool.",schema:r.RequestOperationsSchema,annotations:{title:"Request Operations",readOnlyHint:!1,destructiveHint:!0,idempotentHint:!1},handler(e,t){return(0,n.handleRequestOperations)(e,t.context,t.apiClient,t.logger,t.metrics,t.mcpServer)}}},4192(e,exports,t){"use strict"
|
|
2654
|
+
exports.def={name:"request_operations",description:"Perform operations on existing requests.\n\nOperations:\n\u2022 complete - Begin completion: provide summary, get criteria keys for verification\n\u2022 verify-criteria - Verify acceptance criteria with evidence per key (triggers merge when all verified)\n\u2022 finalize - Approve and merge a request that is ready for review\n\u2022 approve - Approve a pending request so work can begin\n\u2022 revert - Completely revert a completed request, undoing all changes\n\u2022 get-info - Get comprehensive request information\n\u2022 list - List and filter requests. Filters: type, status, dateFrom/dateTo, planDocumentId (narrow to one plan), questDocumentId (narrow to one quest), plus pagination + sort.\n\u2022 search - Full-text search across title/description/criteria with the same filters.\n\u2022 delete-empty - Delete a request that has no tasks (safe cleanup for mistaken or obsolete requests)\n\nCompletion is two-phase: first call complete with a summary, then call verify-criteria with evidence for each criterion key.\n\nNote: To create a new request, use the separate create-request tool.",schema:r.RequestOperationsSchema,annotations:{title:"Request Operations",readOnlyHint:!1,destructiveHint:!0,idempotentHint:!1},handler(e,t){return(0,n.handleRequestOperations)(e,t.context,t.apiClient,t.logger,t.metrics,t.mcpServer)}}},4192(e,exports,t){"use strict"
|
|
2634
2655
|
Object.defineProperty(exports,"__esModule",{value:!0}),exports.BaseApiClient=void 0
|
|
2635
2656
|
const r=t(7163)
|
|
2636
2657
|
exports.BaseApiClient=class{constructor(e,t,n,o,s){this.failureCount=0,this.circuitState="closed",this.circuitResetTimeout=null,this.baseUrl=e,this.logger=t,this.metrics=n,this.authToken=o,this.options={retryAttempts:3,retryDelay:1e3,timeout:1e4,circuitBreakerThreshold:10,circuitBreakerResetTime:1e4,...s},this.logger.debug("BaseApiClient constructor options:",{providedOptions:s?JSON.stringify(s):"undefined",mergedOptions:JSON.stringify(this.options)})
|
|
@@ -2673,7 +2694,10 @@ throw void 0!==r&&500>r||this.incrementFailureCount(),this.logger.error(`API req
|
|
|
2673
2694
|
this.logger.warn(`API request failed, retrying in ${r}ms`,{method:e,url:i,error:t.message||t+"",attempt:l,maxAttempts:d}),await new Promise((e=>setTimeout(e,r)))}}throw Error("Unexpected end of requestWithRetry")}incrementFailureCount(){this.failureCount++,this.metrics.setGauge("api_failure_count",this.failureCount),"half-open"!==this.circuitState?this.failureCount<this.options.circuitBreakerThreshold||"closed"!==this.circuitState||this.openCircuit():this.logger.warn("Half-open probe failed, will retry on next request")}resetFailureCount(){const e="closed"!==this.circuitState
|
|
2674
2695
|
this.failureCount=0,this.circuitState="closed",this.metrics.setGauge("api_failure_count",0),this.metrics.setGauge("circuit_breaker_open",0),this.circuitResetTimeout&&(clearTimeout(this.circuitResetTimeout),this.circuitResetTimeout=null),e&&this.logger.info("Circuit breaker closed after successful request")}openCircuit(){this.circuitState="open",this.metrics.setGauge("circuit_breaker_open",1),this.logger.warn(`Circuit breaker opened after ${this.failureCount} failures`),this.circuitResetTimeout&&clearTimeout(this.circuitResetTimeout)
|
|
2675
2696
|
const e=this.options.circuitBreakerResetTime||5e3
|
|
2676
|
-
this.circuitResetTimeout=setTimeout((()=>{this.circuitState="half-open",this.logger.info("Circuit breaker half-open, next request will probe")}),e)}async get(e,t,r){return this.requestWithRetry("GET",e,void 0,r,t)}async post(e,t,r){return this.requestWithRetry("POST",e,t,r)}async put(e,t,r){return this.requestWithRetry("PUT",e,t,r)}async delete(e,t){return this.requestWithRetry("DELETE",e,void 0,t)}async patch(e,t,r){return this.requestWithRetry("PATCH",e,t,r)}}},
|
|
2697
|
+
this.circuitResetTimeout=setTimeout((()=>{this.circuitState="half-open",this.logger.info("Circuit breaker half-open, next request will probe")}),e)}async get(e,t,r){return this.requestWithRetry("GET",e,void 0,r,t)}async post(e,t,r){return this.requestWithRetry("POST",e,t,r)}async put(e,t,r){return this.requestWithRetry("PUT",e,t,r)}async delete(e,t){return this.requestWithRetry("DELETE",e,void 0,t)}async patch(e,t,r){return this.requestWithRetry("PATCH",e,t,r)}}},4206(e,exports,t){"use strict"
|
|
2698
|
+
Object.defineProperty(exports,"__esModule",{value:!0}),exports.def=void 0
|
|
2699
|
+
const r=t(6183),n=t(1719)
|
|
2700
|
+
exports.def={name:"quest_set_criteria_statuses",description:"Update the status (and optional evidence) of one or more quest criteria (alchemist-only).\n\nUse this when a structured criteria checklist is present on a quest (metadata.criteria is a non-empty array) and you've verified or unverified one or more items.\n\nRequired: questId, updates (array of at least one { id, status, evidence? }).\n\n- id must match an existing criterion in metadata.criteria; unknown ids return an error listing the valid ids so you can correct.\n- status is 'verified' or 'unverified'.\n- evidence is optional free text (file path, request id, test name, command output, etc.) noting why the status changed.\n\nNotes:\n- Updates merge into the existing item (description and other fields preserved); only status and evidence change.\n- This tool only touches criterion statuses. It does NOT bump the audit streak or flip the quest status. Call quest_audit_complete separately when you believe the whole quest is done \u2014 that gate additionally requires all structured criteria to be verified.\n- Safe to call across many ticks as you verify items one by one. Spawning a request under the quest still resets the audit streak via the createRequest hook; per-criterion verification does not.",schema:r.QuestSetCriteriaStatusesSchema,annotations:{title:"Quest Set Criteria Statuses",readOnlyHint:!1,destructiveHint:!1,idempotentHint:!0},handler(e,t){return(0,n.handleQuestSetCriteriaStatuses)(e,t.context,t.apiClient,t.logger,t.metrics)}}},4221(e,exports,t){"use strict"
|
|
2677
2701
|
var r,n=this&&this.__createBinding||(Object.create?function(e,t,r,n){void 0===n&&(n=r)
|
|
2678
2702
|
var o=Object.getOwnPropertyDescriptor(t,r)
|
|
2679
2703
|
o&&!("get"in o?!t.__esModule:o.writable||o.configurable)||(o={enumerable:!0,get(){return t[r]}}),Object.defineProperty(e,n,o)}:function(e,t,r,n){void 0===n&&(n=r),e[n]=t[r]}),o=this&&this.__setModuleDefault||(Object.create?function(e,t){Object.defineProperty(e,"default",{enumerable:!0,value:t})}:function(e,t){e.default=t}),s=this&&this.__importStar||(r=function(e){return r=Object.getOwnPropertyNames||function(e){var t=[]
|
|
@@ -2748,7 +2772,7 @@ let P=null
|
|
|
2748
2772
|
try{i.default.mkdirSync(S,{recursive:!0}),P=i.default.createWriteStream(q,{flags:"w"}),P.write(`# ${(new Date).toISOString()} starting: ${C}\n# cwd: ${E}\n# timeout: ${v.timeout||60}s\n\n`)}catch(e){h.warn("Failed to open command log file",{logPath:q,error:(0,l.getErrorMessage)(e)})}h.info("Running command",{name:v.name,command:C,cwd:E,configuredCwd:v.cwd,logPath:q})
|
|
2749
2773
|
const j=await(0,n.runTrackedShellWithHeartbeat)(C,{cwd:E,timeoutMs:1e3*(v.timeout||60),env:{...process.env,FORCE_COLOR:"0"},onChunk:P?(e,t)=>{P?.write(t)}:void 0},{id:T,name:v.name,sessionId:m?.sessionId,logPath:q},f)
|
|
2750
2774
|
P&&(P.write(`\n# exit: ${j.exitCode}${j.timedOut?" (timed out)":""}\n`),P.end())
|
|
2751
|
-
const{stdout:
|
|
2775
|
+
const{stdout:x,stderr:R,exitCode:M,timedOut:O}=j,{output:$,truncatedNote:D,logFooter:A}=(0,o.formatCommandOutput)(x,R,{invocationId:T}),F=O?"TIMEOUT":null
|
|
2752
2776
|
let N
|
|
2753
2777
|
if(g)try{const e=await g.createToolRecord({projectId:t.projectId,type:"run-command",metadata:{name:v.name,command:C,exitCode:M,timedOut:O,status:O?"timeout":0===M?"success":"failed",timestamp:(new Date).toISOString()}})
|
|
2754
2778
|
N=e?.id}catch(e){h.debug("Failed to create tool record for command run",{error:(0,l.getErrorMessage)(e)})}return y({success:!0}),{content:[{type:"text",text:`## ${v.name}${F?` \u2014 ${F} (killed after ${v.timeout}s)`:""}\n\`\`\`\n$ ${C}\n${$}\n\`\`\`${D}\n\nExit code: ${M}\n${A} (pass to read_files or search)`}],...(0,c.alchemyMeta)({kind:"run-command",toolRecordId:N})}}catch(e){return y({success:!1,error:"api_error"}),{content:[{type:"text",text:"Failed to run command: "+(0,l.getErrorMessage)(e)}],isError:!0}}}
|
|
@@ -3258,7 +3282,23 @@ const e=o.annotationId,t=o.body,r=i.getDocumentClient(),n=await r.replyToAnnotat
|
|
|
3258
3282
|
return c.incrementCounter("document_operations_total",1,{operation:"reply-to-annotation",success:!0}),(0,s.withAlchemyKind)({content:[{type:"text",text:`\u2705 **Reply Added**\n\n**Reply ID:** ${n.id}\n**Annotation:** ${e}\n**Body:** `+t}]},"reply-to-annotation")}case"resolve-annotation":{u.info("Resolving annotation")
|
|
3259
3283
|
const e=o.annotationId,t=i.getDocumentClient()
|
|
3260
3284
|
return await t.resolveAnnotation(h,e,d?"agent":void 0),c.incrementCounter("document_operations_total",1,{operation:"resolve-annotation",success:!0}),(0,s.withAlchemyKind)({content:[{type:"text",text:`\u2705 **Annotation Resolved**\n\n**Annotation:** ${e}\n**Status:** resolved`}]},"resolve-annotation")}default:throw Error("Unknown operation type: "+a)}}catch(e){return u.error("document_operations failed",{error:e instanceof Error?e.stack:e+""}),c.incrementCounter("document_operations_errors",1),{content:[{type:"text",text:"\u274c **Document Operations Failed:** "+(0,o.getErrorMessage)(e)}],isError:!0}}}
|
|
3261
|
-
const r=t(1572),n=t(1483),o=t(8824),s=t(2272)},
|
|
3285
|
+
const r=t(1572),n=t(1483),o=t(8824),s=t(2272)},5652(e,exports,t){"use strict"
|
|
3286
|
+
Object.defineProperty(exports,"__esModule",{value:!0}),exports.handleQuestAuditComplete=async function(e,t,o,s,i){const a=s.child({tool:"quest_audit_complete"})
|
|
3287
|
+
try{if(!t.projectId)return{content:[{type:"text",text:"\u274c No project context available."}],isError:!0}
|
|
3288
|
+
const r=o.getDocumentClient(),s=await r.getDocument(e.questId)
|
|
3289
|
+
if(!s)return{content:[{type:"text",text:"\u274c Quest not found: "+e.questId}],isError:!0}
|
|
3290
|
+
if("Quest"!==s.type)return{content:[{type:"text",text:`\u274c Document ${e.questId} is not a quest (type: ${s.type}). quest_audit_complete only applies to Quest documents.`}],isError:!0}
|
|
3291
|
+
const c=s.metadata||{},l=c.status||n.QUEST_STATUS_OPEN
|
|
3292
|
+
if(l!==n.QUEST_STATUS_OPEN)return{content:[{type:"text",text:`\u274c Quest status is "${l}", not "open". Audits are only valid while the quest is open.`}],isError:!0}
|
|
3293
|
+
const d=c.completionMode,u="auto-close"===d||"audit-then-pending"===d?d:n.QUEST_COMPLETION_MODE_DEFAULT,h=Array.isArray(c.criteria)?c.criteria:[]
|
|
3294
|
+
if(h.length>0){const e=h.filter((e=>"verified"!==e?.status))
|
|
3295
|
+
if(e.length>0){const t=e.map((e=>`- ${e?.id||"(no id)"}: ${e?.description||"(no description)"}`))
|
|
3296
|
+
return{content:[{type:"text",text:`\u274c Cannot complete audit \u2014 ${e.length} of ${h.length} criteria still unverified:\n\n`+t.join("\n")+"\n\nUse quest_set_criteria_statuses to mark each item verified (with evidence), or use plan_write update to remove a criterion that's no longer applicable."}],isError:!0}}}const p=c.minIterations??(0,n.defaultMinIterations)(u),g=c.consecutiveDoneAudits??0,m=g+1,f=m>=p,y=f?"auto-close"===u?n.QUEST_STATUS_CLOSED:n.QUEST_STATUS_PENDING_REVIEW:l,w={...c,consecutiveDoneAudits:f?0:m,status:y}
|
|
3297
|
+
f&&(w.lastAuditSummary=e.summary,w.lastAuditAt=(new Date).toISOString(),e.evidence&&e.evidence.length>0?w.lastAuditEvidence=e.evidence:delete w.lastAuditEvidence),await r.updateDocument(e.questId,{metadata:w}),i.incrementCounter("quest_audit_complete_total",1,{flipped:f+"",completionMode:u,newStatus:y})
|
|
3298
|
+
const b=s.localId||s.id
|
|
3299
|
+
if(a.info("quest_audit_complete processed",{questId:b,previousCounter:g,nextCounter:m,willFlip:f,completionMode:u,nextStatus:y}),!f){const e=p-m
|
|
3300
|
+
return{content:[{type:"text",text:`\u{1f4dd} **Audit recorded (${m}/${p})**\n\nQuest **${b}** still needs ${e} more consistent done-audit${1===e?"":"s"} before status will flip. Keep auditing on future ticks. If criteria regress (you find remaining work and spawn a request), the counter resets to 0.`}]}}return{content:[{type:"text",text:`\u2705 **Audit threshold reached (${m}/${p})**\n\nQuest **${b}**: ${y===n.QUEST_STATUS_CLOSED?"Quest status flipped to **closed** (auto-close mode). The quest is terminal.":"Quest status flipped to **pending_review**. Ticks are paused. The user will close or reopen."}\n\n**Summary stored:** `+e.summary}]}}catch(e){return a.error("quest_audit_complete failed",{error:(0,r.getErrorMessage)(e)}),{content:[{type:"text",text:"\u274c **quest_audit_complete failed:** "+(0,r.getErrorMessage)(e)}],isError:!0}}}
|
|
3301
|
+
const r=t(8824),n=t(3416)},5674(e,exports,t){"use strict"
|
|
3262
3302
|
Object.defineProperty(exports,"__esModule",{value:!0}),exports.ConnectionError=void 0
|
|
3263
3303
|
const r=t(441)
|
|
3264
3304
|
class n extends Error{constructor(e,t,o,s={}){super(e),this.statusCode=503,this.retryable=!0,this.metadata={},this.name="ConnectionError",this.code=r.CONNECTION_ERROR,this.operation=t,this.lastConnectionAttempt=o,this.details={...s,operation:t,lastConnectionAttempt:o},Object.setPrototypeOf(this,n.prototype)}static operationRequiresConnectivity(e,t="",r){const o=`Cannot perform ${e}${t?` (${t})`:""} - not connected to remote server. Please check your network connection and try again. If the problem persists, verify that the remote server is running and accessible.`,s={operationType:e,operationDetails:t,timestamp:(new Date).toISOString(),suggestions:["Check your internet connection","Verify the remote server URL is correct","Ensure the remote server is running","Check for any firewall or proxy settings that might be blocking the connection"]}
|
|
@@ -3295,20 +3335,22 @@ return p.error("Server validation failed",{requestId:n,error:t}),g({success:!1,e
|
|
|
3295
3335
|
return m.blockedByTasks&&m.blockedByTasks.length>0&&(e+="\n**Tasks that must be completed or canceled first:**\n",m.blockedByTasks.forEach(((t,r)=>{e+=`${r+1}. **${t.taskId}** - ${t.title} (Status: ${t.status})\n`}))),m.lifoViolation&&(e+="\n**Requests that must be re-completed first (LIFO order):**\n",m.lifoViolation.blockingRequests.forEach(((t,r)=>{e+=`${r+1}. **${t.requestId}** - ${t.title} (Status: ${t.status})\n`}))),g({success:!1,reason:"server_blocked"}),{content:[{type:"text",text:e}],isError:!0}}if(m.testsSkipped&&(l||d&&d.length>0))try{const e=c.getToolRecordClient()
|
|
3296
3336
|
e&&await e.createToolRecord({projectId:t.projectId,requestId:n,type:"tests-skipped",metadata:{...l?{reason:l}:{},...d&&d.length>0?{skipTests:d}:{},completionMode:m.completionMode,timestamp:(new Date).toISOString()}})}catch(e){p.warn("Failed to persist tests-skipped tool_record",{error:(0,s.getErrorMessage)(e)})}const f=c.getRequestClient()
|
|
3297
3337
|
let y="auto-merge"!==m.completionMode&&!m.testsSkipped
|
|
3298
|
-
const w="manual-review"===m.reviewMode
|
|
3299
|
-
|
|
3338
|
+
const w="manual-review"===m.reviewMode,b=y&&!1===m.hasActiveTestProcesses&&("test-by-default"===m.completionMode||"always-test"===m.completionMode)
|
|
3339
|
+
b&&(y=!1)
|
|
3340
|
+
let I,k=null
|
|
3300
3341
|
if(y)try{const[e,r]=await Promise.all([c.proxyGet(`/api/projects/${t.projectId}/requests/${n}/test-runs`),fetch(`${(0,a.getActionServerBaseUrl)()}/api/branch-head?requestId=${encodeURIComponent(n)}`,{signal:AbortSignal.timeout(5e3)}).catch((e=>(p.debug("branch-head fetch failed; proceeding with ready_for_review",{error:(0,s.getErrorMessage)(e)}),null)))]),o=e?.data||e||[],i=Array.isArray(o)&&o.length>0?o[0]:null
|
|
3301
3342
|
if(i&&"passed"===i.status&&i.commitSha){let e=null
|
|
3302
3343
|
if(r&&r.ok){const t=await r.json()
|
|
3303
|
-
e=t?.data?.sha??null}e&&e===i.commitSha&&(y=!1,
|
|
3304
|
-
try{await f.updateRequest(n,{status:
|
|
3305
|
-
return g({success:!1,error:"status_transition_failed"}),{content:[{type:"text",text:"Failed to transition request: "+t}],isError:!0}}let
|
|
3306
|
-
try{
|
|
3307
|
-
return g({success:!1,error:"fetch_request_failed"}),{content:[{type:"text",text:"Failed to fetch request criteria: "+t}],isError:!0}}const C
|
|
3308
|
-
if(g({success:!0}),y)
|
|
3309
|
-
|
|
3310
|
-
|
|
3311
|
-
|
|
3344
|
+
e=t?.data?.sha??null}e&&e===i.commitSha&&(y=!1,k=`latest test run ${i.id} passed against current branch HEAD ${e.slice(0,7)}`,I=i.id,p.info("Skip-if-fresh: SHA match, bypassing ready_for_review",{requestId:n,runId:i.id,sha:e}))}}catch(e){p.debug("Skip-if-fresh lookup failed; proceeding with ready_for_review",{error:(0,s.getErrorMessage)(e)})}const v=y||w?"ready_for_review":"ready_for_merge"
|
|
3345
|
+
try{await f.updateRequest(n,{status:v,completionSummary:o,...I?{skippedTestRunId:I}:{}})}catch(e){const t=(0,s.getErrorMessage)(e)
|
|
3346
|
+
return g({success:!1,error:"status_transition_failed"}),{content:[{type:"text",text:"Failed to transition request: "+t}],isError:!0}}let C
|
|
3347
|
+
try{C=await f.getRequest(n)}catch(e){const t=(0,s.getErrorMessage)(e)
|
|
3348
|
+
return g({success:!1,error:"fetch_request_failed"}),{content:[{type:"text",text:"Failed to fetch request criteria: "+t}],isError:!0}}const _=C?.acceptanceCriteria||[]
|
|
3349
|
+
if(g({success:!0}),y){const e=m.completionMode
|
|
3350
|
+
let t
|
|
3351
|
+
return t="ask-me"===e?"A notification has been created asking the user to choose how to handle testing (auto-test, interactive-test, or skip).":"always-test"===e?"Tests are running automatically in the background (always-test mode). When they pass and the project is set to auto-finalize, the request will be merged without further input; otherwise the user will click Finalize after reviewing.":"Tests are running automatically in the background (test-by-default mode). When they pass and the project is set to auto-finalize, the request will be merged without further input; otherwise the user will click Finalize after reviewing.",{content:[{type:"text",text:`Request ${n} moved to ready_for_review. ${t} Do NOT call merge or any other tool. Your work is done. Stop here and wait.`}]}}if(w)return{content:[{type:"text",text:`Request ${n} submitted for human review.${m.testsSkipped&&l?`\n\n_Tests skipped: ${l}_`:""}\n\nThe project is set to manual-review \u2014 a person will approve and merge from the UI. Do NOT call merge yourself.`}]}
|
|
3352
|
+
const E=k?`\n\n_Skipped re-running tests: ${k}._\n`:"",S=b?`\n\n_No test processes are configured for this project; ${m.completionMode} mode is being treated as auto-merge._\n`:""
|
|
3353
|
+
return 0===_.length?{content:[{type:"text",text:`Request ${n} is ready. ${E}${S}No acceptance criteria defined \u2014 call merge directly.`}]}:{content:[{type:"text",text:`Request ${n} completion started (${v}).${E}${S}\n\n## Next Step: Verify & Merge\n\n${(0,i.formatVerifyInstructions)(_)}\n\nUse the merge operation with your verification evidence to merge to main.`}]}}catch(r){let s="An unexpected error occurred",i=""
|
|
3312
3354
|
r instanceof n.ZodError?(s="Validation error",i=r.errors.map((e=>`${e.path.join(".")}: ${e.message}`)).join(", ")):r instanceof Error?(s=r.message,i=r.stack||""):i=r+"",p.error("Complete request failed",{error:s,details:i})
|
|
3313
3355
|
try{await(0,o.createFailureToolRecord)("complete-request",r,{error:s,details:i,requestId:e?.requestId},c.getToolRecordClient(),p,d,{requestId:e?.requestId,projectId:t.projectId,note:"Failed to complete request"})}catch{}return d.startTimer("tool_execution_time")({success:!1,error:r instanceof Error?r.name:"unknown"}),{content:[{type:"text",text:"Error: "+s}],isError:!0}}}
|
|
3314
3356
|
const r=t(9860),n=t(1569),o=t(8616),s=t(8824),i=t(5454),a=t(9414)},5767(e,exports,t){"use strict"
|
|
@@ -3349,50 +3391,50 @@ else{if(!E)throw Error("Either paths or operations must be specified")
|
|
|
3349
3391
|
j=E.map((e=>{if(e.path)return{type:"file",target:e.path}
|
|
3350
3392
|
if(e.documentId)return{type:"document",target:e.documentId}
|
|
3351
3393
|
throw Error("Invalid operation: neither path nor documentId specified")}))}if(0===j.length)throw Error("At least one file or document must be specified for deletion")
|
|
3352
|
-
const
|
|
3353
|
-
m.info("Starting mixed file and document deletion operation",{taskId:P,totalOperations:j.length,fileOperations:
|
|
3394
|
+
const x=j.filter((e=>"file"===e.type)),R=j.filter((e=>"document"===e.type)),M=j.length
|
|
3395
|
+
m.info("Starting mixed file and document deletion operation",{taskId:P,totalOperations:j.length,fileOperations:x.length,documentOperations:R.length,comment:S}),c.validateTaskIdFormat(P,m,s,I.metricsPrefix)
|
|
3354
3396
|
const O=r.getCurrentBranchContext?await r.getCurrentBranchContext():{branch:null,requestId:null,isMain:!0}
|
|
3355
3397
|
m.info("Initial branch context",{initialBranch:O.branch,initialRequestId:O.requestId,isMain:O.isMain})
|
|
3356
3398
|
const $=[]
|
|
3357
|
-
for(const e of
|
|
3399
|
+
for(const e of x){const{normalizedPath:t,fullPath:n}=c.validateAndNormalizePath(e.target,r)
|
|
3358
3400
|
$.push({normalized:t,full:n})}b=c.FileOperationPhase.TASK_VALIDATION,s.incrementCounter("delete_files_phase",1,{phase:b})
|
|
3359
3401
|
const D=$.length>0?$[0].normalized:"document_operations",A=await c.validateTaskId(P,D,d,m,s,I.metricsPrefix),F=A?.requestId,N=await c.validateWorkItemStates(P,D,d,v,r,m,s,I.metricsPrefix),z=await c.autoPromoteTaskStatus(P,A.status,F,N.request?.status,D,d,v,m,s,I.metricsPrefix)
|
|
3360
|
-
z.taskPromoted&&m.info(`Auto-promoted task ${P} (${A.title||"Untitled"}) to in_progress for mixed operations`,{taskId:P,taskTitle:A.title,previousStatus:A.status,newStatus:z.newTaskStatus,totalOperations:j.length,fileOperations:
|
|
3402
|
+
z.taskPromoted&&m.info(`Auto-promoted task ${P} (${A.title||"Untitled"}) to in_progress for mixed operations`,{taskId:P,taskTitle:A.title,previousStatus:A.status,newStatus:z.newTaskStatus,totalOperations:j.length,fileOperations:x.length,documentOperations:R.length}),z.requestPromoted&&m.info(`Auto-promoted request ${F} to in_progress for file operations`,{requestId:F,previousStatus:N.request?.status,newStatus:z.newRequestStatus,triggeringTaskId:P})
|
|
3361
3403
|
const L=await c.ensureCorrectWorkspaceContext({taskPromoted:z.taskPromoted,requestId:F,context:r,operation:"delete-files",logger:m,metrics:s,metricsPrefix:I.metricsPrefix})
|
|
3362
3404
|
if(!L.success)throw Error(L.error)
|
|
3363
3405
|
let H={hadUserMods:!1,userModsCommitHash:void 0}
|
|
3364
3406
|
if(r.git)try{m.debug("[DELETE-FILES] Checking for user changes before mixed delete operations")
|
|
3365
3407
|
const e=await(0,u.commitUserChangesBeforeToolOperation)(r.git,"delete-files",{requestId:F,taskId:P,workspaceManager:r.workspaceManager},m,s)
|
|
3366
|
-
e.userChangesCommitted&&(m.debug("[DELETE-FILES] User changes committed before mixed delete operations",{commitHash:e.commitHash?.substring(0,8),filesCommitted:e.filesCommitted}),m.info("User changes committed before mixed delete-files operation",{taskId:P,totalOperations:j.length,fileOperations:
|
|
3367
|
-
const{toolRecordId:B,localToolRecordId:U}=await c.createFileOperationRecords(P,F,r.projectId,I.recordType,D,{totalOperations:j.length,fileOperations:
|
|
3408
|
+
e.userChangesCommitted&&(m.debug("[DELETE-FILES] User changes committed before mixed delete operations",{commitHash:e.commitHash?.substring(0,8),filesCommitted:e.filesCommitted}),m.info("User changes committed before mixed delete-files operation",{taskId:P,totalOperations:j.length,fileOperations:x.length,documentOperations:R.length,userCommitHash:e.commitHash?.substring(0,8),userFilesCommitted:e.filesCommitted}),H={hadUserMods:!0,userModsCommitHash:e.commitHash})}catch(e){m.debug("[DELETE-FILES] Pre-tool commit failed, continuing with mixed delete operations",{error:e instanceof Error?e.message:e+""}),m.warn("Pre-tool user changes commit failed, continuing with mixed delete operation",{taskId:P,totalOperations:j.length,fileOperations:x.length,documentOperations:R.length,error:e instanceof Error?e.message:e+""})}m.debug("[DELETE-FILES] Proceeding with mixed delete operations",{totalOperations:j.length,fileDeletes:x.length,documentDeletes:R.length}),b=c.FileOperationPhase.RECORD_CREATION,s.incrementCounter("delete_files_phase",1,{phase:b})
|
|
3409
|
+
const{toolRecordId:B,localToolRecordId:U}=await c.createFileOperationRecords(P,F,r.projectId,I.recordType,D,{totalOperations:j.length,fileOperations:x.length,documentOperations:R.length,filePaths:$.map((e=>e.normalized)),documentIds:R.map((e=>e.target)),userComment:S,hadUserMods:H.hadUserMods,userModsCommitHash:H.userModsCommitHash},d,k,m,s,I.metricsPrefix,i)
|
|
3368
3410
|
y=B,w=B,b=I.fileOperationPhase,s.incrementCounter("delete_files_phase",1,{phase:b})
|
|
3369
3411
|
const G=[]
|
|
3370
3412
|
let W=0
|
|
3371
|
-
|
|
3413
|
+
R.length>0&&n.setProjectId(r.projectId)
|
|
3372
3414
|
for(let e=0;e<$.length;e++){const t=$[e],r={type:"file",path:t.normalized,success:!1,replacements:[],successfulReplacements:0,failedReplacements:0}
|
|
3373
3415
|
try{try{await a.default.access(t.full)}catch(e){throw Error("File not found: "+t.normalized)}if((await a.default.stat(t.full)).isDirectory())throw Error("Cannot 'delete' a directory: "+t.normalized)
|
|
3374
|
-
await a.default.unlink(t.full),r.success=!0,W++,m.info("Successfully deleted file",{path:t.normalized})}catch(e){r.error=(0,g.getErrorMessage)(e),m.warn("Failed to delete file "+t.normalized,{error:r.error})}G.push(r)}const V=
|
|
3375
|
-
for(const e of
|
|
3416
|
+
await a.default.unlink(t.full),r.success=!0,W++,m.info("Successfully deleted file",{path:t.normalized})}catch(e){r.error=(0,g.getErrorMessage)(e),m.warn("Failed to delete file "+t.normalized,{error:r.error})}G.push(r)}const V=R.length>0?n.getDocumentClient():null
|
|
3417
|
+
for(const e of R){const t=e.target,r={type:"document",documentId:t,success:!1,replacements:[],successfulReplacements:0,failedReplacements:0}
|
|
3376
3418
|
try{let e
|
|
3377
3419
|
try{if(e=await V.getDocument(t),r.filename=e.filename,m.info("Document found for archival",{documentId:e.id,filename:e.filename,type:e.type,requestId:e.requestId}),e.requestId)try{await(0,h.validateRequestStatusForDocumentOperation)(e.requestId,v,m,s,"delete-document")}catch(e){if(e instanceof l.ValidationError)throw Error(e.message)
|
|
3378
3420
|
throw e}try{await(0,p.ensureDocumentNotLocked)(t,n,m,s,"delete-document-archive")}catch(e){if(e instanceof l.ValidationError)throw Error(e.message)
|
|
3379
3421
|
throw e}}catch(e){throw Error(`Document not found or validation failed: ${t}. ${(0,g.getErrorMessage)(e)}`)}const o=await V.archiveDocument(t)
|
|
3380
|
-
r.success=!0,r.filename=o.filename,W++,m.info("Document archived successfully",{documentId:o.id,filename:o.filename,archivedAt:o.archived_at})}catch(e){r.error=(0,g.getErrorMessage)(e),m.warn("Failed to delete document "+t,{error:r.error})}G.push(r)}const
|
|
3381
|
-
s.recordValue("delete_files_time",
|
|
3382
|
-
let
|
|
3422
|
+
r.success=!0,r.filename=o.filename,W++,m.info("Document archived successfully",{documentId:o.id,filename:o.filename,archivedAt:o.archived_at})}catch(e){r.error=(0,g.getErrorMessage)(e),m.warn("Failed to delete document "+t,{error:r.error})}G.push(r)}const Q=Date.now()-f
|
|
3423
|
+
s.recordValue("delete_files_time",Q),s.incrementCounter("delete_files_operations_total",M),s.incrementCounter("delete_files_operations_success",W),s.incrementCounter("delete_files_operations_failed",M-W),s.incrementCounter("delete_files_file_operations",x.length),s.incrementCounter("delete_files_document_operations",R.length),W===M?s.incrementCounter("delete_files_success",1):W>0?s.incrementCounter("delete_files_partial_success",1):s.incrementCounter("delete_files_total_failure",1)
|
|
3424
|
+
let K=null
|
|
3383
3425
|
if(W>0){b=c.FileOperationPhase.GIT_COMMIT,s.incrementCounter("delete_files_phase",1,{phase:b})
|
|
3384
3426
|
const e=G.filter((e=>e.success)),t=e.filter((e=>"file"===e.type)).length,n=e.filter((e=>"document"===e.type)).length
|
|
3385
3427
|
let o
|
|
3386
|
-
o=t>0&&n>0?`Delete ${t} files and ${n} documents - ${S}`:t>0?1===t?"Delete file - "+S:`Delete ${t} files - ${S}`:1===n?"Delete document - "+S:`Delete ${n} documents - ${S}`,
|
|
3387
|
-
const
|
|
3388
|
-
await c.updateFileOperationRecords(P,y,w,D,I.recordType,W===M?`Successfully deleted all ${M} operations`:`Deleted ${W}/${M} operations successfully`,{status:W===M?"completed":"partial_success",commitHash:
|
|
3428
|
+
o=t>0&&n>0?`Delete ${t} files and ${n} documents - ${S}`:t>0?1===t?"Delete file - "+S:`Delete ${t} files - ${S}`:1===n?"Delete document - "+S:`Delete ${n} documents - ${S}`,K=await c.commitToGit(P,D,B,U,o,r,m,s,I.metricsPrefix)}b=c.FileOperationPhase.RECORD_UPDATE_SUCCESS,s.incrementCounter("delete_files_phase",1,{phase:b})
|
|
3429
|
+
const J=G.filter((e=>e.success)),Y=G.filter((e=>!e.success))
|
|
3430
|
+
await c.updateFileOperationRecords(P,y,w,D,I.recordType,W===M?`Successfully deleted all ${M} operations`:`Deleted ${W}/${M} operations successfully`,{status:W===M?"completed":"partial_success",commitHash:K?.commitHash,previousCommitHash:K?.previousCommitHash,totalOperations:M,fileOperations:x.length,documentOperations:R.length,successCount:W,failureCount:M-W,successfulOperations:J.map((e=>({type:e.type,path:e.path,documentId:e.documentId,filename:e.filename}))),failedOperations:Y.map((e=>({type:e.type,path:e.path,documentId:e.documentId,filename:e.filename,error:e.error}))),userComment:S,hadUserMods:H.hadUserMods,userModsCommitHash:H.userModsCommitHash},W===M?`Successfully deleted all ${M} operations`:`Deleted ${W}/${M} operations successfully`,d,k,m,s,I.metricsPrefix)
|
|
3389
3431
|
const Z=r.getCurrentBranchContext?await r.getCurrentBranchContext():{branch:null,requestId:null,isMain:!0}
|
|
3390
3432
|
let X=""
|
|
3391
|
-
if(W===M){const e=
|
|
3433
|
+
if(W===M){const e=J.filter((e=>"file"===e.type)).length,t=J.filter((e=>"document"===e.type)).length
|
|
3392
3434
|
X=e>0&&t>0?`Successfully deleted ${e} files and ${t} documents`:e>0?`Successfully deleted all ${e} ${1===e?"file":"files"}`:`Successfully archived all ${t} ${1===t?"document":"documents"}`}else X=W>0?`Successfully deleted ${W}/${M} operations.\n\nFailed operations:\n`+G.filter((e=>!e.success)).map((e=>{const t="file"===e.type?e.path:`${e.filename||e.documentId} (${e.documentId})`
|
|
3393
3435
|
return`\u2022 ${e.type}: ${t}: ${e.error}`})).join("\n"):"All delete operations failed:\n"+G.map((e=>{const t="file"===e.type?e.path:`${e.filename||e.documentId} (${e.documentId})`
|
|
3394
3436
|
return`\u2022 ${e.type}: ${t}: ${e.error}`})).join("\n")
|
|
3395
|
-
return
|
|
3437
|
+
return K?.commitHash&&(X+="\nCommit: "+K.commitHash.substring(0,8)),Z.requestId&&(X+="\nBranch: "+Z.requestId),{content:[{type:"text",text:X}],isError:0===W}}catch(t){if(e.taskId&&n)try{const o=n.getToolRecordClient(),s=t instanceof l.NotFoundError||t instanceof l.ValidationError||t instanceof d.ZodError
|
|
3396
3438
|
await o.createToolRecord({...s?{}:{taskId:e.taskId},projectId:r.projectId,type:"delete-files",metadata:{status:"failed",timestamp:(new Date).toISOString(),totalOperations:e.operations?.length||e.paths?.length||0,fileOperations:e.paths?.length||e.operations?.filter((e=>e.path))?.length||0,documentOperations:e.operations?.filter((e=>e.documentId))?.length||0,paths:e.paths||e.operations?.filter((e=>e.path))?.map((e=>e.path))||[],documentIds:e.operations?.filter((e=>e.documentId))?.map((e=>e.documentId))||[],userComment:e.comment,error:(0,g.getErrorMessage)(t),errorDetails:t instanceof Error?t.stack:t+"",phase:b,attemptedTaskId:e.taskId,taskIdValidationFailed:s},note:"Failed to delete files - "+(0,g.getErrorMessage)(t)})}catch(t){m.error("Failed to create failure record for delete-files operation",{error:t instanceof Error?t.message:t+"",taskId:e.taskId,totalOperations:e.operations?.length||e.paths?.length||0,fileOperations:e.paths?.length||e.operations?.filter((e=>e.path))?.length||0,documentOperations:e.operations?.filter((e=>e.documentId))?.length||0})}const o=Date.now()-f
|
|
3397
3439
|
if(s.recordValue("delete_files_time",o),s.incrementCounter("delete_files_errors",1),m.error("Error in delete-files operation:",{error:(0,g.getErrorMessage)(t),time:o}),(y||w)&&e.taskId){b=c.FileOperationPhase.RECORD_UPDATE_FAILURE
|
|
3398
3440
|
try{const r=n.getTaskClient(),o=n.getToolRecordClient()
|
|
@@ -3459,22 +3501,25 @@ const n=await this.requestWithRetry("POST","/api/files/recover",t)
|
|
|
3459
3501
|
if(!(0,i.safeGetResponseData)(n,null))throw new r.ServiceError("Empty response when recovering file")
|
|
3460
3502
|
const o=(0,i.safeGetResponseData)(n,{success:!0,path:e.path,commitHash:e.commitHash,backupPath:void 0})
|
|
3461
3503
|
return this.logger.info("Successfully recovered file "+e.path,{path:o.path,commitHash:o.commitHash,backupPath:o.backupPath}),o}catch(t){throw this.logger.error("Failed to recover file "+e.path,{path:e.path,commitHash:e.commitHash,error:t instanceof Error?t.stack:t+""}),t}}}exports.FileOperationsClient=a},6183(e,exports,t){"use strict"
|
|
3462
|
-
Object.defineProperty(exports,"__esModule",{value:!0}),exports.DocumentOperationsSchema=exports.SearchDocumentsSchema=exports.CreateDocumentSchema=exports.ReplaceLinesSchema=exports.InsertLinesSchema=exports.SwitchToRequestBranchSchema=exports.PlannerOpsSchema=exports.SpecialistOpsSchema=exports.SubagentOperationsSchema=exports.TaskInspectSchema=exports.CompleteTaskSchema=exports.GetTaskInformationSchema=exports.GetRequestInformationSchema=exports.ListRequestsSchema=exports.ListTasksSchema=exports.SearchSchema=exports.QueryHistorySchema=exports.RequestDiffSchema=exports.FileRecoverSchema=exports.FileHistorySchema=exports.DeleteFilesSchema=exports.DeleteFileSchema=exports.ReplaceInFilesSchema=exports.ReplaceStringsSchema=exports.ReplaceStringSchema=exports.MoveFilesSchema=exports.CreateDirectorySchema=exports.GetFileInfoSchema=exports.ListDirectorySchema=exports.ReadFilesSchema=exports.ViewAssetSchema=exports.WriteFileSchema=exports.UpdateTaskStatusSchema=exports.CreateTaskSchema=exports.CreateRequestSchema=exports.CompleteRequestSchema=exports.skipTestsSchema=exports.skipTestsReasonSchema=exports.ExecutedTestSchema=exports.TestVerificationSchema=exports.TestDefinitionSchema=exports.AcceptanceCriterionSchema=exports.RecordTypeEnum=exports.EvidenceTypeEnum=exports.CriterionStatusEnum=exports.RequestStatusEnum=exports.TaskStatusEnum=exports.RequestTypeEnum=exports.TestCoverageTypeEnum=exports.CompletionStatusEnum=void 0,exports.CommitToViewedSessionSchema=exports.UpdateSpecializationSchema=exports.SessionMessageOperationsSchema=exports.ReportTestResultsSchema=exports.CommandsSchema=exports.ExecuteTestCommandSchema=exports.TestsSchema=exports.TestingReferenceSchema=exports.TestingProcessUpdateSchema=exports.TestingProcessDeleteSchema=exports.TestingProcessCreateSchema=exports.TestingProcessGetSchema=exports.TestingProcessListSchema=exports.MetaReferenceSchema=exports.MetaAgentListSchema=exports.MetaWorkflowRemoveRecipeSchema=exports.MetaWorkflowAddRecipeSchema=exports.MetaHookCreateSchema=exports.MetaHookListSchema=exports.MetaRecipeRemoveHookSchema=exports.MetaRecipeAddHookSchema=exports.MetaRecipeCreateSchema=exports.MetaRecipeGetSchema=exports.MetaRecipeListSchema=exports.MetaWorkflowUpdateSchema=exports.MetaWorkflowCreateSchema=exports.MetaWorkflowGetSchema=exports.MetaWorkflowListSchema=exports.GenerateRequestJournalSchema=exports.QuickManageSchema=exports.QuickReplaceSchema=exports.QuickWriteSchema=exports.RequestOperationsSchema=exports.ManageFilesSchema=exports.ModifyFileSchema=exports.RevertRequestSchema=exports.SwitchToBranchSchema=exports.SwitchToMainBranchSchema=exports.PlanWriteSchema=exports.PlanReadSchema=void 0
|
|
3463
|
-
const r=t(1569),n=t(8955),o=t(4466),s=(e,t,n={})=>r.z.string().refine((t=>!(!n.allowEmpty||""!==t)||!!t&&e.some((e=>e.test(t)))),{message:t}),i
|
|
3464
|
-
exports.CompletionStatusEnum=r.z.enum(["complete","incomplete","partial"]),exports.TestCoverageTypeEnum=r.z.enum(["unit","e2e","integration","manual"]),exports.RequestTypeEnum=r.z.enum(["feature","bugfix","quick-edit"]),exports.TaskStatusEnum=r.z.enum(["pending","in_progress","ready_for_review","completed","canceled","reverted"]),exports.RequestStatusEnum=r.z.enum(["open","in_progress","ready_for_review","ready_for_merge","completed","canceled","reverted","conflicted"]),exports.CriterionStatusEnum=r.z.enum(["unverified","verified"]),exports.EvidenceTypeEnum=r.z.enum(["test","manual","other"]),exports.RecordTypeEnum=r.z.enum(["write","modify","blocker","resolution","discovery","test","delete"]),exports.AcceptanceCriterionSchema=r.z.object({description:r.z.string(),status:r.z.enum(["unverified","verified"]).default("unverified"),evidence:r.z.string().optional(),evidenceType:r.z.enum(["test","manual","other"]).optional(),createdAt:r.z.string().optional(),updatedAt:r.z.string().optional()}),exports.TestDefinitionSchema=r.z.object({id:r.z.string(),description:r.z.string(),status:exports.CompletionStatusEnum,coverageType:exports.TestCoverageTypeEnum,accepts:r.z.array(r.z.string())}),exports.TestVerificationSchema=r.z.object({criteria:r.z.array(r.z.string()),tests:r.z.array(r.z.string()),coverageType:exports.TestCoverageTypeEnum,coverageRatio:r.z.number(),createdAt:r.z.string().optional(),updatedAt:r.z.string().optional()}),exports.ExecutedTestSchema=r.z.object({id:r.z.string(),testId:r.z.string(),status:exports.CompletionStatusEnum,results:r.z.string(),coverage:r.z.array(r.z.string()),executedAt:r.z.string()}),exports.skipTestsReasonSchema=r.z.string().min(20).optional().describe("Optional: opt out of ALL tests for this completion. Provide >=20 chars explaining why. Rejected in always-test projects. For per-test opt-out use `skipTests` instead."),exports.skipTestsSchema=r.z.array(r.z.object({commandName:r.z.string().min(1).describe("Name of the test command to skip (must match a command registered in an active test_process)."),reason:r.z.string().min(20).describe("Why this specific command is irrelevant to the change (>=20 chars).")})).optional().describe("Optional: skip individual test commands by name. Mutually exclusive with skipTestsReason. Rejected in always-test projects."),exports.CompleteRequestSchema=r.z.object({status:exports.RequestStatusEnum,acceptanceCriteria:r.z.array(exports.AcceptanceCriterionSchema),testVerification:exports.TestVerificationSchema.optional(),completionSummary:r.z.string().optional()}),exports.CreateRequestSchema=r.z.object({title:r.z.string(),type:r.z.enum(["feature","bugfix"]),description:r.z.string(),acceptanceCriteria:r.z.array(r.z.string()),planDocumentId:r.z.string().optional(),questDocumentId:r.z.string().optional()}),exports.CreateTaskSchema=r.z.object({requestId:a,title:r.z.string(),description:r.z.string()}),exports.UpdateTaskStatusSchema=r.z.object({taskId:i,status:exports.TaskStatusEnum,note:r.z.string()}),exports.WriteFileSchema=r.z.object({path:r.z.string().optional(),documentId:c.optional(),content:r.z.union([r.z.string(),r.z.array(r.z.string())]),format:r.z.enum(["text","json"]).optional(),append:r.z.boolean().optional(),comment:r.z.string()}).transform(l).refine(d,{message:"path or documentId required"}),exports.ViewAssetSchema=r.z.object({filename:r.z.string().describe("The asset filename (e.g., 01JMXYZ.png)")}),exports.ReadFilesSchema=r.z.object({paths:r.z.array(r.z.object({path:r.z.string().optional(),documentId:c.optional(),lines:r.z.string().optional()}).transform(l).refine(d,{message:"path or documentId required"})),encoding:r.z.enum(["utf8","utf-8","ascii","binary"]).optional()}),exports.ListDirectorySchema=r.z.object({path:r.z.string(),levels:r.z.number().min(1).max(4).optional(),sortBy:r.z.enum(["name","modified","size","type"]).optional()}),exports.GetFileInfoSchema=r.z.object({path:r.z.string()}),exports.CreateDirectorySchema=r.z.object({path:r.z.string(),comment:r.z.string().optional()}),exports.MoveFilesSchema=r.z.object({operations:r.z.array(r.z.object({source:r.z.string(),destination:r.z.string()})),comment:r.z.string()}),exports.ReplaceStringSchema=r.z.object({path:r.z.string(),replacements:r.z.array(r.z.object({old_str:r.z.string(),new_str:r.z.string()})),mode:r.z.enum(["unique","all"]).optional(),comment:r.z.string()}),exports.ReplaceStringsSchema=r.z.object({operations:r.z.array(r.z.object({path:r.z.string().optional(),documentId:c.optional(),replacements:r.z.array(r.z.object({old_str:r.z.string(),new_str:r.z.string()})),mode:r.z.enum(["unique","all"]).optional()}).transform(l).refine(d,{message:"path or documentId required"})),comment:r.z.string()}),exports.ReplaceInFilesSchema=r.z.object({operations:r.z.array(r.z.object({path:r.z.string().optional(),documentId:c.optional(),replacements:r.z.array(r.z.object({old:r.z.string().min(1,"old string cannot be empty"),new:r.z.string(),match_mode:r.z.enum(["unique","all"]).optional()})).min(1,"At least one replacement required"),fuzzy_match:r.z.boolean().optional()}).transform(l).refine(d,{message:"path or documentId required"})).min(1,"At least one operation required"),fuzzy_match:r.z.boolean().optional().default(!0),comment:r.z.string()}),exports.DeleteFileSchema=r.z.object({path:r.z.string(),comment:r.z.string()}),exports.DeleteFilesSchema=r.z.object({paths:r.z.array(r.z.string()).optional(),operations:r.z.array(r.z.object({path:r.z.string().optional(),documentId:c.optional()}).transform(l).refine(d,{message:"path or documentId required"})).optional(),comment:r.z.string()}).refine((e=>e.paths&&!e.operations||!e.paths&&e.operations),{message:"paths or operations required"}).refine((e=>e.paths?.length||e.operations?.length),{message:"path/operation required"}),exports.FileHistorySchema=r.z.object({path:r.z.string(),limit:r.z.number().min(1).max(100).default(10),showDiff:r.z.boolean().default(!1),showTraceability:r.z.boolean().default(!0),branch:r.z.string().optional(),commit:r.z.string().optional(),since:r.z.string().optional()}),exports.FileRecoverSchema=r.z.object({path:r.z.string(),commitHash:r.z.string(),createBackup:r.z.boolean().default(!0)}),exports.RequestDiffSchema=r.z.object({requestId:a,format:r.z.enum(["summary","unified"]).default("summary"),path:r.z.string().optional()}),exports.QueryHistorySchema=r.z.object({queryType:r.z.enum(["file-history","request-file-history","recover","blame"],{errorMap(){return{message:"Invalid queryType. Valid options: file-history, request-file-history, recover, blame"}}}),fileHistory:r.z.object({path:r.z.string(),limit:r.z.number().min(1).max(100).default(10),showDiff:r.z.boolean().default(!1),showTraceability:r.z.boolean().default(!0),branch:r.z.string().optional(),commit:r.z.string().optional(),since:r.z.string().optional()}).optional(),requestHistory:r.z.object({requestId:a,detailLevel:r.z.enum(["summary","detailed"]).default("summary"),taskId:i.optional(),showDiff:r.z.boolean().optional(),fileFilter:r.z.string().optional()}).optional(),recover:r.z.object({path:r.z.string(),commitHash:r.z.string().optional(),createBackup:r.z.boolean().default(!0)}).optional(),blame:r.z.object({path:r.z.string(),lines:r.z.string().optional(),branch:r.z.string().optional()}).optional()}).refine((e=>"file-history"===e.queryType?e.fileHistory&&!e.requestHistory&&!e.recover:"request-file-history"===e.queryType?e.requestHistory&&!e.fileHistory&&!e.recover:"recover"===e.queryType?e.recover&&!e.fileHistory&&!e.requestHistory&&!e.blame:"blame"===e.queryType&&e.blame&&!e.fileHistory&&!e.requestHistory&&!e.recover),{message:"Invalid query data"}),exports.SearchSchema=r.z.object({needle:r.z.string().optional(),directory:r.z.string().optional(),options:r.z.object({caseSensitive:r.z.boolean().optional(),fileExtension:r.z.string().optional(),maxResults:r.z.number().optional(),useRegex:r.z.boolean().optional(),searchIn:r.z.enum(["content","filename","both"]).default("content").optional(),contextLines:r.z.number().min(0).max(10).optional(),levels:r.z.number().min(1).max(4).optional(),sortBy:r.z.enum(["name","modified","size","type"]).optional()}).optional()}),exports.ListTasksSchema=r.z.object({requestId:a,filters:r.z.object({status:r.z.enum(["pending","in_progress","ready_for_review","completed","canceled","reverted"]).optional(),limit:r.z.number().min(1).max(100).default(20),offset:r.z.number().min(0).default(0),sortBy:r.z.enum(["created","updated"]).default("updated"),sortDirection:r.z.enum(["asc","desc"]).default("desc")}).optional()}),exports.ListRequestsSchema=r.z.object({filters:r.z.object({type:r.z.enum(["feature","bugfix"]).optional(),status:r.z.enum(["open","in_progress","ready_for_review","completed","canceled"]).optional(),planDocumentId:r.z.string().optional(),questDocumentId:r.z.string().optional(),dateFrom:r.z.string().optional(),dateTo:r.z.string().optional(),limit:r.z.number().min(1).max(100).default(20),offset:r.z.number().min(0).default(0),sortBy:r.z.enum(["created","updated"]).default("updated"),sortDirection:r.z.enum(["asc","desc"]).default("desc")}).optional()}),exports.GetRequestInformationSchema=r.z.object({requestId:a}),exports.GetTaskInformationSchema=r.z.object({taskId:i}),exports.CompleteTaskSchema=r.z.object({taskId:i,summary:r.z.string()}),exports.TaskInspectSchema=r.z.object({operation:r.z.enum(["get-info","list"]),taskId:i.optional(),requestId:a.optional(),status:r.z.enum(["pending","in_progress","ready_for_review","completed","canceled","reverted"]).optional(),limit:r.z.number().min(1).max(100).default(20),offset:r.z.number().min(0).default(0),sortBy:r.z.enum(["created","updated"]).default("updated"),sortDirection:r.z.enum(["asc","desc"]).default("desc")}).superRefine(((e,t)=>{"get-info"!==e.operation||e.taskId||t.addIssue({code:"custom",message:'taskId is required for get-info. Example: { "operation": "get-info", "taskId": "req000001#01" }'}),"list"!==e.operation||e.requestId||t.addIssue({code:"custom",message:'requestId is required for list. Example: { "operation": "list", "requestId": "req000001" }'})}))
|
|
3465
|
-
const
|
|
3466
|
-
exports.SubagentOperationsSchema=r.z.object({sessionId:
|
|
3467
|
-
const
|
|
3468
|
-
exports.PlanReadSchema=r.z.object({operation:r.z.enum(["get","get-active","list","get-history","get-requests"]),planId:
|
|
3469
|
-
if("create"===r
|
|
3470
|
-
|
|
3504
|
+
Object.defineProperty(exports,"__esModule",{value:!0}),exports.DocumentOperationsSchema=exports.SearchDocumentsSchema=exports.CreateDocumentSchema=exports.ReplaceLinesSchema=exports.InsertLinesSchema=exports.SwitchToRequestBranchSchema=exports.PlannerOpsSchema=exports.SpecialistOpsSchema=exports.SubagentOperationsSchema=exports.TaskInspectSchema=exports.CompleteTaskSchema=exports.GetTaskInformationSchema=exports.GetRequestInformationSchema=exports.ListRequestsSchema=exports.ListTasksSchema=exports.SearchSchema=exports.QueryHistorySchema=exports.RequestDiffSchema=exports.FileRecoverSchema=exports.FileHistorySchema=exports.DeleteFilesSchema=exports.DeleteFileSchema=exports.ReplaceInFilesSchema=exports.ReplaceStringsSchema=exports.ReplaceStringSchema=exports.MoveFilesSchema=exports.CreateDirectorySchema=exports.GetFileInfoSchema=exports.ListDirectorySchema=exports.ReadFilesSchema=exports.ViewAssetSchema=exports.WriteFileSchema=exports.UpdateTaskStatusSchema=exports.CreateTaskSchema=exports.CreateRequestSchema=exports.CompleteRequestSchema=exports.skipTestsSchema=exports.skipTestsReasonSchema=exports.ExecutedTestSchema=exports.TestVerificationSchema=exports.TestDefinitionSchema=exports.AcceptanceCriterionSchema=exports.RecordTypeEnum=exports.EvidenceTypeEnum=exports.CriterionStatusEnum=exports.RequestStatusEnum=exports.TaskStatusEnum=exports.RequestTypeEnum=exports.TestCoverageTypeEnum=exports.CompletionStatusEnum=void 0,exports.CommitToViewedSessionSchema=exports.UpdateSpecializationSchema=exports.SessionMessageOperationsSchema=exports.ReportTestResultsSchema=exports.CommandsSchema=exports.ExecuteTestCommandSchema=exports.TestsSchema=exports.TestingReferenceSchema=exports.TestingProcessUpdateSchema=exports.TestingProcessDeleteSchema=exports.TestingProcessCreateSchema=exports.TestingProcessGetSchema=exports.TestingProcessListSchema=exports.MetaReferenceSchema=exports.MetaAgentListSchema=exports.MetaWorkflowRemoveRecipeSchema=exports.MetaWorkflowAddRecipeSchema=exports.MetaHookCreateSchema=exports.MetaHookListSchema=exports.MetaRecipeRemoveHookSchema=exports.MetaRecipeAddHookSchema=exports.MetaRecipeCreateSchema=exports.MetaRecipeGetSchema=exports.MetaRecipeListSchema=exports.MetaWorkflowUpdateSchema=exports.MetaWorkflowCreateSchema=exports.MetaWorkflowGetSchema=exports.MetaWorkflowListSchema=exports.GenerateRequestJournalSchema=exports.QuickManageSchema=exports.QuickReplaceSchema=exports.QuickWriteSchema=exports.RequestOperationsSchema=exports.ManageFilesSchema=exports.ModifyFileSchema=exports.RevertRequestSchema=exports.SwitchToBranchSchema=exports.SwitchToMainBranchSchema=exports.QuestAuditCompleteSchema=exports.QuestSetCriteriaStatusesSchema=exports.PlanWriteSchema=exports.PlanReadSchema=void 0
|
|
3505
|
+
const r=t(1569),n=t(8955),o=t(4466),s=t(3416),i=(e,t,n={})=>r.z.string().refine((t=>!(!n.allowEmpty||""!==t)||!!t&&e.some((e=>e.test(t)))),{message:t}),a=i([o.TASK_REF_PATTERN,o.TASK_REF_SHORT_PATTERN],"Task ID must be req######+#NN (e.g. req000005#03) or a short form like #01, 01, or 1 (resolved against the active request)."),c=i([/^req\d{6}$/],"Request ID must match format: req###### (e.g. req000001)"),l=i([/^doc_[0-9A-Z]{26}$/i,/^(doc|plan|quest|jour)\d{6}$/],"Document ID must match format: doc_[26 alphanumeric] (ULID) or doc######/plan######/quest######/jour###### (local ID)",{allowEmpty:!0}),d=e=>e.path&&e.documentId?{...e,documentId:void 0}:e,u=e=>!!e.path||!!e.documentId
|
|
3506
|
+
exports.CompletionStatusEnum=r.z.enum(["complete","incomplete","partial"]),exports.TestCoverageTypeEnum=r.z.enum(["unit","e2e","integration","manual"]),exports.RequestTypeEnum=r.z.enum(["feature","bugfix","quick-edit"]),exports.TaskStatusEnum=r.z.enum(["pending","in_progress","ready_for_review","completed","canceled","reverted"]),exports.RequestStatusEnum=r.z.enum(["open","in_progress","ready_for_review","ready_for_merge","completed","canceled","reverted","conflicted"]),exports.CriterionStatusEnum=r.z.enum(["unverified","verified"]),exports.EvidenceTypeEnum=r.z.enum(["test","manual","other"]),exports.RecordTypeEnum=r.z.enum(["write","modify","blocker","resolution","discovery","test","delete"]),exports.AcceptanceCriterionSchema=r.z.object({description:r.z.string(),status:r.z.enum(["unverified","verified"]).default("unverified"),evidence:r.z.string().optional(),evidenceType:r.z.enum(["test","manual","other"]).optional(),createdAt:r.z.string().optional(),updatedAt:r.z.string().optional()}),exports.TestDefinitionSchema=r.z.object({id:r.z.string(),description:r.z.string(),status:exports.CompletionStatusEnum,coverageType:exports.TestCoverageTypeEnum,accepts:r.z.array(r.z.string())}),exports.TestVerificationSchema=r.z.object({criteria:r.z.array(r.z.string()),tests:r.z.array(r.z.string()),coverageType:exports.TestCoverageTypeEnum,coverageRatio:r.z.number(),createdAt:r.z.string().optional(),updatedAt:r.z.string().optional()}),exports.ExecutedTestSchema=r.z.object({id:r.z.string(),testId:r.z.string(),status:exports.CompletionStatusEnum,results:r.z.string(),coverage:r.z.array(r.z.string()),executedAt:r.z.string()}),exports.skipTestsReasonSchema=r.z.string().min(20).optional().describe("Optional: opt out of ALL tests for this completion. Provide >=20 chars explaining why. Rejected in always-test projects. For per-test opt-out use `skipTests` instead."),exports.skipTestsSchema=r.z.array(r.z.object({commandName:r.z.string().min(1).describe("Name of the test command to skip (must match a command registered in an active test_process)."),reason:r.z.string().min(20).describe("Why this specific command is irrelevant to the change (>=20 chars).")})).optional().describe("Optional: skip individual test commands by name. Mutually exclusive with skipTestsReason. Rejected in always-test projects."),exports.CompleteRequestSchema=r.z.object({status:exports.RequestStatusEnum,acceptanceCriteria:r.z.array(exports.AcceptanceCriterionSchema),testVerification:exports.TestVerificationSchema.optional(),completionSummary:r.z.string().optional()}),exports.CreateRequestSchema=r.z.object({title:r.z.string(),type:r.z.enum(["feature","bugfix"]),description:r.z.string(),acceptanceCriteria:r.z.array(r.z.string()),planDocumentId:r.z.string().optional(),questDocumentId:r.z.string().optional()}),exports.CreateTaskSchema=r.z.object({requestId:c,title:r.z.string(),description:r.z.string()}),exports.UpdateTaskStatusSchema=r.z.object({taskId:a,status:exports.TaskStatusEnum,note:r.z.string()}),exports.WriteFileSchema=r.z.object({path:r.z.string().optional(),documentId:l.optional(),content:r.z.union([r.z.string(),r.z.array(r.z.string())]),format:r.z.enum(["text","json"]).optional(),append:r.z.boolean().optional(),comment:r.z.string()}).transform(d).refine(u,{message:"path or documentId required"}),exports.ViewAssetSchema=r.z.object({filename:r.z.string().describe("The asset filename (e.g., 01JMXYZ.png)")}),exports.ReadFilesSchema=r.z.object({paths:r.z.array(r.z.object({path:r.z.string().optional(),documentId:l.optional(),lines:r.z.string().optional()}).transform(d).refine(u,{message:"path or documentId required"})),encoding:r.z.enum(["utf8","utf-8","ascii","binary"]).optional()}),exports.ListDirectorySchema=r.z.object({path:r.z.string(),levels:r.z.number().min(1).max(4).optional(),sortBy:r.z.enum(["name","modified","size","type"]).optional()}),exports.GetFileInfoSchema=r.z.object({path:r.z.string()}),exports.CreateDirectorySchema=r.z.object({path:r.z.string(),comment:r.z.string().optional()}),exports.MoveFilesSchema=r.z.object({operations:r.z.array(r.z.object({source:r.z.string(),destination:r.z.string()})),comment:r.z.string()}),exports.ReplaceStringSchema=r.z.object({path:r.z.string(),replacements:r.z.array(r.z.object({old_str:r.z.string(),new_str:r.z.string()})),mode:r.z.enum(["unique","all"]).optional(),comment:r.z.string()}),exports.ReplaceStringsSchema=r.z.object({operations:r.z.array(r.z.object({path:r.z.string().optional(),documentId:l.optional(),replacements:r.z.array(r.z.object({old_str:r.z.string(),new_str:r.z.string()})),mode:r.z.enum(["unique","all"]).optional()}).transform(d).refine(u,{message:"path or documentId required"})),comment:r.z.string()}),exports.ReplaceInFilesSchema=r.z.object({operations:r.z.array(r.z.object({path:r.z.string().optional(),documentId:l.optional(),replacements:r.z.array(r.z.object({old:r.z.string().min(1,"old string cannot be empty"),new:r.z.string(),match_mode:r.z.enum(["unique","all"]).optional()})).min(1,"At least one replacement required"),fuzzy_match:r.z.boolean().optional()}).transform(d).refine(u,{message:"path or documentId required"})).min(1,"At least one operation required"),fuzzy_match:r.z.boolean().optional().default(!0),comment:r.z.string()}),exports.DeleteFileSchema=r.z.object({path:r.z.string(),comment:r.z.string()}),exports.DeleteFilesSchema=r.z.object({paths:r.z.array(r.z.string()).optional(),operations:r.z.array(r.z.object({path:r.z.string().optional(),documentId:l.optional()}).transform(d).refine(u,{message:"path or documentId required"})).optional(),comment:r.z.string()}).refine((e=>e.paths&&!e.operations||!e.paths&&e.operations),{message:"paths or operations required"}).refine((e=>e.paths?.length||e.operations?.length),{message:"path/operation required"}),exports.FileHistorySchema=r.z.object({path:r.z.string(),limit:r.z.number().min(1).max(100).default(10),showDiff:r.z.boolean().default(!1),showTraceability:r.z.boolean().default(!0),branch:r.z.string().optional(),commit:r.z.string().optional(),since:r.z.string().optional()}),exports.FileRecoverSchema=r.z.object({path:r.z.string(),commitHash:r.z.string(),createBackup:r.z.boolean().default(!0)}),exports.RequestDiffSchema=r.z.object({requestId:c,format:r.z.enum(["summary","unified"]).default("summary"),path:r.z.string().optional()}),exports.QueryHistorySchema=r.z.object({queryType:r.z.enum(["file-history","request-file-history","recover","blame"],{errorMap(){return{message:"Invalid queryType. Valid options: file-history, request-file-history, recover, blame"}}}),fileHistory:r.z.object({path:r.z.string(),limit:r.z.number().min(1).max(100).default(10),showDiff:r.z.boolean().default(!1),showTraceability:r.z.boolean().default(!0),branch:r.z.string().optional(),commit:r.z.string().optional(),since:r.z.string().optional()}).optional(),requestHistory:r.z.object({requestId:c,detailLevel:r.z.enum(["summary","detailed"]).default("summary"),taskId:a.optional(),showDiff:r.z.boolean().optional(),fileFilter:r.z.string().optional()}).optional(),recover:r.z.object({path:r.z.string(),commitHash:r.z.string().optional(),createBackup:r.z.boolean().default(!0)}).optional(),blame:r.z.object({path:r.z.string(),lines:r.z.string().optional(),branch:r.z.string().optional()}).optional()}).refine((e=>"file-history"===e.queryType?e.fileHistory&&!e.requestHistory&&!e.recover:"request-file-history"===e.queryType?e.requestHistory&&!e.fileHistory&&!e.recover:"recover"===e.queryType?e.recover&&!e.fileHistory&&!e.requestHistory&&!e.blame:"blame"===e.queryType&&e.blame&&!e.fileHistory&&!e.requestHistory&&!e.recover),{message:"Invalid query data"}),exports.SearchSchema=r.z.object({needle:r.z.string().optional(),directory:r.z.string().optional(),options:r.z.object({caseSensitive:r.z.boolean().optional(),fileExtension:r.z.string().optional(),maxResults:r.z.number().optional(),useRegex:r.z.boolean().optional(),searchIn:r.z.enum(["content","filename","both"]).default("content").optional(),contextLines:r.z.number().min(0).max(10).optional(),levels:r.z.number().min(1).max(4).optional(),sortBy:r.z.enum(["name","modified","size","type"]).optional()}).optional()}),exports.ListTasksSchema=r.z.object({requestId:c,filters:r.z.object({status:r.z.enum(["pending","in_progress","ready_for_review","completed","canceled","reverted"]).optional(),limit:r.z.number().min(1).max(100).default(20),offset:r.z.number().min(0).default(0),sortBy:r.z.enum(["created","updated"]).default("updated"),sortDirection:r.z.enum(["asc","desc"]).default("desc")}).optional()}),exports.ListRequestsSchema=r.z.object({filters:r.z.object({type:r.z.enum(["feature","bugfix"]).optional(),status:r.z.enum(["open","in_progress","ready_for_review","completed","canceled"]).optional(),planDocumentId:r.z.string().optional(),questDocumentId:r.z.string().optional(),dateFrom:r.z.string().optional(),dateTo:r.z.string().optional(),limit:r.z.number().min(1).max(100).default(20),offset:r.z.number().min(0).default(0),sortBy:r.z.enum(["created","updated"]).default("updated"),sortDirection:r.z.enum(["asc","desc"]).default("desc")}).optional()}),exports.GetRequestInformationSchema=r.z.object({requestId:c}),exports.GetTaskInformationSchema=r.z.object({taskId:a}),exports.CompleteTaskSchema=r.z.object({taskId:a,summary:r.z.string()}),exports.TaskInspectSchema=r.z.object({operation:r.z.enum(["get-info","list"]),taskId:a.optional(),requestId:c.optional(),status:r.z.enum(["pending","in_progress","ready_for_review","completed","canceled","reverted"]).optional(),limit:r.z.number().min(1).max(100).default(20),offset:r.z.number().min(0).default(0),sortBy:r.z.enum(["created","updated"]).default("updated"),sortDirection:r.z.enum(["asc","desc"]).default("desc")}).superRefine(((e,t)=>{"get-info"!==e.operation||e.taskId||t.addIssue({code:"custom",message:'taskId is required for get-info. Example: { "operation": "get-info", "taskId": "req000001#01" }'}),"list"!==e.operation||e.requestId||t.addIssue({code:"custom",message:'requestId is required for list. Example: { "operation": "list", "requestId": "req000001" }'})}))
|
|
3507
|
+
const h=r.z.string().min(1).describe("OpenCode session ID")
|
|
3508
|
+
exports.SubagentOperationsSchema=r.z.object({sessionId:h.optional(),operation:r.z.enum(["spawn","continue","check-status","abort","read-messages","list-sessions"]),prompt:r.z.string().min(1).describe("Instructions for the subagent (required for spawn and continue)").optional(),agent:r.z.string().default("work").refine((e=>(0,n.isValidAgent)(e)),{message:"Invalid agent. Check tool description for available agents."}).describe("The subagent type to spawn (see tool description for available agents)").optional(),description:r.z.string().max(60).describe("Brief label for the UI (max 60 chars, spawn only)").optional(),requestId:r.z.string().describe("Request ID \u2014 associates work (spawn) or filters results (list-sessions)").optional(),allowParallel:r.z.boolean().describe("Allow spawning even if request already has active workers (spawn only)").optional(),useExistingSession:r.z.string().describe("Existing session ID to send prompt to instead of creating new session (spawn only)").optional(),limit:r.z.number().min(1).max(100).describe("Max items to return (read-messages: max 50, list-sessions: max 100)").optional(),activeOnly:r.z.boolean().describe("Only show sessions that are currently active/busy (list-sessions only)").optional(),minTokens:r.z.number().min(0).describe("Only show sessions with at least this many tokens (list-sessions only)").optional(),maxTokens:r.z.number().min(0).describe("Only show sessions with at most this many tokens (list-sessions only)").optional(),maxAgeHours:r.z.number().min(0).describe("Only show sessions newer than X hours (list-sessions only)").optional()}).refine((e=>"spawn"===e.operation?!!e.prompt:"continue"===e.operation?!!e.prompt&&!!e.sessionId:"check-status"===e.operation||"abort"===e.operation||"read-messages"===e.operation?!!e.sessionId:"list-sessions"===e.operation),{message:"spawn requires prompt; continue requires prompt+sessionId; check-status/abort/read-messages require sessionId"}),exports.SpecialistOpsSchema=r.z.object({operation:r.z.enum(["delegate","follow-up","check-status","list","abort"]),sessionId:h.optional(),prompt:r.z.string().min(1).describe("Instructions for the specialist (required for delegate and follow-up)").optional(),description:r.z.string().max(60).describe("Brief label for the UI (max 60 chars, delegate only)").optional(),specialization:r.z.string().max(500).describe('Domain description (e.g. "Frontend UI components"). Required for delegate').optional(),specializationHeadline:r.z.string().max(80).describe("Optional short tagline (\u226480 chars) shown next to the specialist\u2019s name in the UI directory. The specialist can refine it later via update_specialization.").optional(),requestId:r.z.string().describe("Request ID \u2014 associates work (delegate) or filters results (list)").optional(),activeOnly:r.z.boolean().describe("Only show active/busy specialists (list only)").optional(),limit:r.z.number().min(1).max(100).describe("Max sessions to return (list only)").optional()}).refine((e=>"delegate"===e.operation?!!e.prompt&&!!e.specialization&&!e.sessionId:"follow-up"===e.operation?!!e.prompt&&!!e.sessionId:"check-status"===e.operation||"abort"===e.operation?!!e.sessionId:"list"===e.operation),{message:"delegate requires prompt+specialization; follow-up requires prompt+sessionId; check-status/abort require sessionId"}),exports.PlannerOpsSchema=r.z.object({operation:r.z.enum(["request","check-status","list"]),sessionId:h.optional(),prompt:r.z.string().min(1).describe("What to plan \u2014 feature description, architecture question, etc. (required for request)").optional(),description:r.z.string().max(60).describe("Brief label for the UI (max 60 chars, request only)").optional(),activeOnly:r.z.boolean().describe("Only show active/busy planning sessions (list only)").optional(),limit:r.z.number().min(1).max(100).describe("Max sessions to return (list only)").optional()}).refine((e=>"request"===e.operation?!!e.prompt:"check-status"===e.operation?!!e.sessionId:"list"===e.operation),{message:"request requires prompt; check-status requires sessionId"}),exports.SwitchToRequestBranchSchema=r.z.object({requestId:c}),exports.InsertLinesSchema=r.z.object({operations:r.z.array(r.z.object({path:r.z.string().optional(),documentId:l.optional(),insertions:r.z.array(r.z.object({type:r.z.enum(["before","after","between"]),line:r.z.number().optional(),afterLine:r.z.number().optional(),beforeLine:r.z.number().optional(),content:r.z.union([r.z.string(),r.z.array(r.z.string())])}).refine((e=>"between"===e.type?void 0!==e.afterLine&&void 0!==e.beforeLine&&void 0===e.line:void 0!==e.line&&void 0===e.afterLine&&void 0===e.beforeLine),{message:"Invalid line parameters"}))}).transform(d).refine(u,{message:"path or documentId required"})),comment:r.z.string()}),exports.ReplaceLinesSchema=r.z.object({operations:r.z.array(r.z.object({path:r.z.string().optional(),documentId:l.optional(),replacements:r.z.array(r.z.object({lines:r.z.string(),content:r.z.union([r.z.string(),r.z.array(r.z.string())])}))}).transform(d).refine(u,{message:"path or documentId required"})),comment:r.z.string()}),exports.CreateDocumentSchema=r.z.object({requestId:c.optional(),filename:r.z.string().refine((e=>e.toLowerCase().endsWith(".md")),{message:"Filename must end with .md extension"}),content:r.z.string(),type:r.z.enum(["Report","Documentation","Plan","Other"],{errorMap(){return{message:"Document type must be one of: Report, Documentation, Plan, Other"}}}),comment:r.z.string()}),exports.SearchDocumentsSchema=r.z.object({query:r.z.string(),type:r.z.enum(["Report","Documentation","Plan","Other"]).optional(),requestId:c.optional(),includeArchived:r.z.boolean().default(!1),maxResults:r.z.number().min(1).max(100).default(20),dateFrom:r.z.string().optional(),dateTo:r.z.string().optional(),searchIn:r.z.enum(["content","filename","both"]).default("both")}),exports.DocumentOperationsSchema=r.z.object({operation:r.z.enum(["create","search","create-snapshot","get-history","get-version","restore-version","list-annotations","create-annotation","reply-to-annotation","resolve-annotation"]),documentId:l.optional(),requestId:c.optional(),filename:r.z.string().optional(),content:r.z.string().optional(),type:r.z.enum(["Report","Documentation","Plan","Other"]).optional(),comment:r.z.string().optional(),query:r.z.string().optional(),includeArchived:r.z.boolean().default(!1),maxResults:r.z.number().min(1).max(100).default(20),dateFrom:r.z.string().optional(),dateTo:r.z.string().optional(),searchIn:r.z.enum(["content","filename","both"]).default("both"),versionLabel:r.z.string().optional(),changeSummary:r.z.string().optional(),versionNumber:r.z.number().int().min(1).optional(),selectedText:r.z.string().optional(),prefixContext:r.z.string().optional(),suffixContext:r.z.string().optional(),lineHint:r.z.number().int().optional(),body:r.z.string().optional(),annotationId:r.z.string().optional()}).superRefine(((e,t)=>{const r=e.operation;["create-snapshot","get-history","get-version","restore-version","list-annotations","create-annotation","reply-to-annotation","resolve-annotation"].includes(r)&&!e.documentId&&t.addIssue({code:"custom",message:`documentId is required for '${r}'. Example: { "operation": "${r}", "documentId": "doc000001" }`}),"create"===r&&(e.filename?e.filename.toLowerCase().endsWith(".md")||t.addIssue({code:"custom",message:"Filename must end with .md extension"}):t.addIssue({code:"custom",message:"filename is required for create (must end with .md)"}),e.content||t.addIssue({code:"custom",message:"content is required for create"}),e.type||t.addIssue({code:"custom",message:"type is required for create (Report, Documentation, Plan, or Other)"}),e.comment||t.addIssue({code:"custom",message:"comment is required for create"})),"search"!==r||e.query||t.addIssue({code:"custom",message:'query is required for search. Example: { "operation": "search", "query": "search term" }'}),"get-version"!==r&&"restore-version"!==r||e.versionNumber||t.addIssue({code:"custom",message:`versionNumber is required for '${r}'`}),"create-annotation"===r&&(e.selectedText||t.addIssue({code:"custom",message:"selectedText is required for create-annotation"}),e.body||t.addIssue({code:"custom",message:"body is required for create-annotation"})),"reply-to-annotation"===r&&(e.annotationId||t.addIssue({code:"custom",message:"annotationId is required for reply-to-annotation"}),e.body||t.addIssue({code:"custom",message:"body is required for reply-to-annotation"})),"resolve-annotation"!==r||e.annotationId||t.addIssue({code:"custom",message:"annotationId is required for resolve-annotation"})}))
|
|
3509
|
+
const p=i([/^doc_[0-9A-Z]{26}$/i,/^(plan|quest)\d{6}$/],"Plan ID must match format: doc_[26 alphanumeric] (ULID) or plan######/quest###### (local ID)")
|
|
3510
|
+
exports.PlanReadSchema=r.z.object({operation:r.z.enum(["get","get-active","list","get-history","get-requests"]),planId:p.optional(),searchQuery:r.z.string().optional(),limit:r.z.number().min(1).max(100).default(20),offset:r.z.number().min(0).default(0),sortBy:r.z.enum(["createdAt","updatedAt","filename"]).default("updatedAt"),sortDirection:r.z.enum(["ASC","DESC"]).default("DESC")}).superRefine(((e,t)=>{["get","get-history","get-requests"].includes(e.operation)&&!e.planId&&t.addIssue({code:"custom",message:`planId is required for '${e.operation}'. Example: { "operation": "${e.operation}", "planId": "plan000001" }`})})),exports.PlanWriteSchema=r.z.object({operation:r.z.enum(["create","update","append","replace","create-snapshot","restore","set-active"]),planId:p.optional(),kind:r.z.enum(["plan"]).default("plan").describe("Document kind to create. Plans only. Quests are created via the UI flow at /quests/new (Start Quest button); the MCP path was removed because no agent calls it. plan_write update still works on existing Quest documents."),criteria:r.z.array(r.z.object({id:r.z.string().min(1).describe("Stable identifier for this criterion (any unique string within the quest, e.g. a slug or ulid)."),description:r.z.string().min(1).describe("What the criterion is, in plain language."),status:r.z.enum(["unverified","verified"]).optional().describe("Per-item verification state. Defaults to unverified when omitted."),evidence:r.z.string().optional().describe("Optional notes / file references / test names that justify the status.")})).optional().describe("Optional structured criteria checklist for the quest. When present, each item has its own verifiable status and the UI shows per-item progress. When omitted, criteria prose lives in the document body (Goal / Criteria for done / Notes) and the alchemist audits it as free text. Update-only \u2014 settable via plan_write update on an existing Quest document. Replaces the entire array (no per-item merge)."),tickIntervalSeconds:r.z.number().int().min(300).optional().describe("Quest heartbeat interval (seconds). Update-only. Minimum 300 (5 min)."),maxInFlight:r.z.number().int().min(1).optional().describe("Quest fan-out width \u2014 max parallel requests per tick. Update-only."),maxPerDay:r.z.number().int().min(1).optional().describe("Quest daily spawn cap. Update-only."),minIterations:r.z.number().int().min(1).optional().describe("Quest minimum consecutive criteria-met audits before quest_audit_complete may flip status. Update-only. Each tick where the alchemist calls quest_audit_complete bumps the audit counter; creating a request under the quest resets it to 0. The state transition only fires once the counter reaches this threshold."),status:r.z.enum(["open","pending_review","closed"]).optional().describe('Quest lifecycle status. Update-only. "open" runs the tick loop; "pending_review" pauses ticks awaiting user adjudication (set by the LLM after its done-audit, in audit-then-pending completion mode); "closed" is terminal. The LLM cannot set "closed" directly \u2014 only the user closes a quest. Quest creation seeds status="draft" via the UI; the quest-planner flips to "open" once configuration is confirmed.'),completionMode:r.z.enum(["auto-close","audit-then-pending"]).optional().describe('Quest completion mode \u2014 controls what happens when the alchemist\'s audit reports criteria are met. Update-only. "auto-close": LLM closes the quest directly. "audit-then-pending" (UI default): LLM flips to pending_review for user adjudication.'),content:r.z.string().optional(),name:r.z.string().optional().describe("Plan/quest name (used in filename for create; optional new name for update)."),old:r.z.string().optional().describe("Text to find in the plan (for replace)"),new:r.z.string().optional().describe("Replacement text (for replace)"),versionLabel:r.z.string().optional(),changeSummary:r.z.string().optional(),versionNumber:r.z.number().int().min(1).optional()}).superRefine(((e,t)=>{const r=e.operation
|
|
3511
|
+
if("create"===r){e.name||t.addIssue({code:"custom",message:"name is required for 'create'. Letters, numbers, hyphens, underscores only."}),void 0===e.content&&t.addIssue({code:"custom",message:"content is required for 'create' (use empty string for an empty body)."})
|
|
3512
|
+
const r=s.QUEST_METADATA_KEYS.filter((t=>void 0!==e[t]))
|
|
3513
|
+
r.length>0&&t.addIssue({code:"custom",message:`Quest metadata fields (${r.join(", ")}) are not allowed on plan_write create. Quests are created via the UI flow at /quests/new. plan_write update still works on existing Quest documents.`})}else e.planId||t.addIssue({code:"custom",message:`planId is required for '${r}'.`})
|
|
3514
|
+
if("append"!==r||e.content||t.addIssue({code:"custom",message:'content is required for \'append\'. Example: { "operation": "append", "planId": "plan000001", "content": "..." }'}),"update"===r){const r=void 0!==e.content,n=void 0!==e.criteria||void 0!==e.tickIntervalSeconds||void 0!==e.maxInFlight||void 0!==e.maxPerDay||void 0!==e.minIterations||void 0!==e.status||void 0!==e.completionMode
|
|
3515
|
+
r||n||t.addIssue({code:"custom",message:"update requires either 'content' (plan or quest body) or at least one metadata field (criteria, tickIntervalSeconds, maxInFlight, maxPerDay, minIterations, status, completionMode \u2014 quest only)."})}"replace"===r&&(e.old||t.addIssue({code:"custom",message:'old is required for replace. Example: { "operation": "replace", "planId": "plan000001", "old": "find this", "new": "replace with" }'}),void 0===e.new&&t.addIssue({code:"custom",message:"new is required for replace"})),"restore"!==r||e.versionNumber||t.addIssue({code:"custom",message:'versionNumber is required for restore. Example: { "operation": "restore", "planId": "plan000001", "versionNumber": 1 }'})})),exports.QuestSetCriteriaStatusesSchema=r.z.object({questId:r.z.string().min(1).describe("The quest documentId whose criteria to update."),updates:r.z.array(r.z.object({id:r.z.string().min(1).describe("Criterion id (must match an existing item in metadata.criteria)."),status:r.z.enum(["unverified","verified"]).describe("New status for this criterion."),evidence:r.z.string().optional().describe("Optional evidence note (file path, request id, test name, command output, etc.) describing why the status changed.")})).min(1).describe("One or more per-criterion updates. Each id must exist in the quest's metadata.criteria; unknown ids return an error listing the valid ids. Updates merge into the existing item (other fields preserved); only status and evidence change.")}),exports.QuestAuditCompleteSchema=r.z.object({questId:r.z.string().min(1).describe("The quest documentId to audit (the long uuid form returned by plan_write create, or the project-scoped doc000NN id)."),summary:r.z.string().min(1).describe("Short prose summary of what evidence the audit found. Stored on the quest if this call reaches the threshold and flips status \u2014 visible to the user when they review."),evidence:r.z.array(r.z.string()).optional().describe("Optional list of evidence references (file paths, request IDs, test names, command outputs) that support the audit conclusion. Stored on the quest alongside the summary if status flips.")}),exports.SwitchToMainBranchSchema=r.z.object({}),exports.SwitchToBranchSchema=r.z.object({branch:r.z.string().optional()}),exports.RevertRequestSchema=r.z.object({requestId:c,reason:r.z.string(),confirmDestructive:r.z.boolean().optional()}),exports.ModifyFileSchema=r.z.object({operations:r.z.array(r.z.object({path:r.z.string().optional(),documentId:l.optional(),operationType:r.z.enum(["replace-string","insert-lines","replace-lines","delete-string","delete-lines"]),replaceString:r.z.object({replacements:r.z.array(r.z.object({old_str:r.z.string(),new_str:r.z.string()})),mode:r.z.enum(["unique","all"]).optional()}).optional(),insertLines:r.z.object({insertions:r.z.array(r.z.object({type:r.z.enum(["before","after","between"]),line:r.z.number().optional(),afterLine:r.z.number().optional(),beforeLine:r.z.number().optional(),content:r.z.union([r.z.string(),r.z.array(r.z.string())])}).refine((e=>"between"===e.type?void 0!==e.afterLine&&void 0!==e.beforeLine&&void 0===e.line:void 0!==e.line&&void 0===e.afterLine&&void 0===e.beforeLine),{message:"Invalid line parameters"}))}).optional(),replaceLines:r.z.object({replacements:r.z.array(r.z.object({lines:r.z.string(),content:r.z.union([r.z.string(),r.z.array(r.z.string())])}))}).optional(),deleteString:r.z.object({patterns:r.z.array(r.z.string()),mode:r.z.enum(["all","unique"]).optional()}).optional(),deleteLines:r.z.object({lines:r.z.string()}).optional()}).transform(d).refine(u,{message:"path or documentId required"}).refine((e=>"replace-string"===e.operationType?e.replaceString&&!e.insertLines&&!e.replaceLines&&!e.deleteString&&!e.deleteLines:"insert-lines"===e.operationType?e.insertLines&&!e.replaceString&&!e.replaceLines&&!e.deleteString&&!e.deleteLines:"replace-lines"===e.operationType?e.replaceLines&&!e.replaceString&&!e.insertLines&&!e.deleteString&&!e.deleteLines:"delete-string"===e.operationType?e.deleteString&&!e.replaceString&&!e.insertLines&&!e.replaceLines&&!e.deleteLines:"delete-lines"===e.operationType&&e.deleteLines&&!e.replaceString&&!e.insertLines&&!e.replaceLines&&!e.deleteString),{message:"Invalid operation data"})),comment:r.z.string()}),exports.ManageFilesSchema=r.z.object({operations:r.z.array(r.z.object({operationType:r.z.enum(["create-directory","move-files","delete-files","get-file-info"]),createDirectory:r.z.object({path:r.z.string()}).optional(),moveFiles:r.z.object({moves:r.z.array(r.z.object({source:r.z.string(),destination:r.z.string()}))}).optional(),deleteFiles:r.z.object({targets:r.z.array(r.z.object({path:r.z.string().optional(),documentId:l.optional()}).transform(d).refine(u,{message:"path or documentId required"}))}).optional(),getFileInfo:r.z.object({path:r.z.string()}).optional()}).refine((e=>"create-directory"===e.operationType?e.createDirectory&&!e.moveFiles&&!e.deleteFiles&&!e.getFileInfo:"move-files"===e.operationType?e.moveFiles&&!e.createDirectory&&!e.deleteFiles&&!e.getFileInfo:"delete-files"===e.operationType?e.deleteFiles&&!e.createDirectory&&!e.moveFiles&&!e.getFileInfo:"get-file-info"===e.operationType&&e.getFileInfo&&!e.createDirectory&&!e.moveFiles&&!e.deleteFiles),{message:"Invalid operation data"})),comment:r.z.string()}),exports.RequestOperationsSchema=r.z.object({requestId:c.optional(),operation:r.z.enum(["complete","merge","approve","revert","get-info","list","search","delete-empty"]),complete:r.z.preprocess((e=>"string"==typeof e?(()=>{try{return JSON.parse(e)}catch{return e}})():e),r.z.object({summary:r.z.string(),skipTestsReason:exports.skipTestsReasonSchema,skipTests:exports.skipTestsSchema})).optional(),merge:r.z.preprocess((e=>"string"==typeof e?(()=>{try{return JSON.parse(e)}catch{return e}})():e),r.z.object({verifications:r.z.array(r.z.object({key:r.z.string().min(2).max(4),evidence:r.z.string().min(1)})).min(1)})).optional(),revert:r.z.object({reason:r.z.string(),confirmDestructive:r.z.boolean().optional()}).optional(),list:r.z.object({filters:r.z.object({type:r.z.enum(["feature","bugfix"]).optional(),status:r.z.enum(["pending_approval","open","in_progress","ready_for_review","ready_for_merge","resolving_conflicts","completed","canceled"]).optional(),planDocumentId:r.z.string().optional().describe("Narrow to requests linked to this Plan document (use the plan's id or local id)."),questDocumentId:r.z.string().optional().describe("Narrow to requests spawned under this Quest document (use the quest's id or local id)."),dateFrom:r.z.string().optional(),dateTo:r.z.string().optional(),limit:r.z.number().min(1).max(100).default(20),offset:r.z.number().min(0).default(0),sortBy:r.z.enum(["created","updated"]).default("updated"),sortDirection:r.z.enum(["asc","desc"]).default("desc")}).optional()}).optional(),search:r.z.object({query:r.z.string().min(1),searchIn:r.z.enum(["title","description","criteria","all"]).default("all"),filters:r.z.object({type:r.z.enum(["feature","bugfix"]).optional(),status:r.z.enum(["pending_approval","open","in_progress","ready_for_review","ready_for_merge","resolving_conflicts","completed","canceled"]).optional(),planDocumentId:r.z.string().optional().describe("Narrow to requests linked to this Plan document."),questDocumentId:r.z.string().optional().describe("Narrow to requests spawned under this Quest document."),dateFrom:r.z.string().optional(),dateTo:r.z.string().optional(),limit:r.z.number().min(1).max(100).default(20),offset:r.z.number().min(0).default(0)}).optional()}).optional(),approve:r.z.object({}).optional()}).superRefine(((e,t)=>{e.requestId
|
|
3471
3516
|
const r=e.operation,n={complete:{field:"complete",hint:'Provide: { complete: { summary: "..." } }'},merge:{field:"merge",hint:'Provide: { merge: { verifications: [{key: "1a", evidence: "..."}] } }'},revert:{field:"revert",hint:'Provide: { revert: { reason: "..." } }'},search:{field:"search",hint:'Provide: { search: { query: "..." } }'}}[r]
|
|
3472
|
-
n&&!e[n.field]&&t.addIssue({code:"custom",message:`'${r}' operation requires '${n.field}' data. ${n.hint}`})})),exports.QuickWriteSchema=r.z.object({title:r.z.string().min(1,"Title is required"),description:r.z.string().min(1,"Description is required"),path:r.z.string().optional(),documentId:
|
|
3473
|
-
const
|
|
3474
|
-
exports.TestingProcessCreateSchema=r.z.object({name:r.z.string().min(1).describe("Name for the test process"),description:r.z.string().optional().describe("Description of what this process verifies"),scope:r.z.string().optional().describe('Path prefix for monorepo scoping (e.g., "packages/api/"). Omit for global.'),setup:r.z.array(r.z.string()).optional().describe('Commands to prepare the environment (e.g., ["ln -s ../../node_modules node_modules"])'),commands:r.z.array(p).min(1).describe("Test commands to execute in order"),verifyAcceptanceCriteria:r.z.boolean().optional().describe("When true, auto-tester verifies request acceptance criteria after running commands"),fingerprint:r.z.array(r.z.string()).optional().describe('Files whose content invalidates setup. Setup commands re-run only when these files change between runs (e.g. ["package-lock.json"], ["Cargo.lock"], ["uv.lock", "poetry.lock"]). Polyglot repos list multiple. Omit / empty list = always re-run setup (existing behavior).'),poolSize:r.z.number().int().min(1).max(8).optional().describe("Number of warm test worktrees in the pool. Default 2. Set to 1 for languages with very large build artifacts (Rust target/, C++ build/). Higher values allow more parallel test runs at the cost of disk.")}),exports.TestingProcessDeleteSchema=r.z.object({processId:r.z.string().describe("Test process ID to delete")}),exports.TestingProcessUpdateSchema=r.z.object({processId:r.z.string().describe("Test process ID to update"),name:r.z.string().min(1).optional().describe("New name"),description:r.z.string().optional().describe("New description"),scope:r.z.string().optional().describe('New scope to limit when this process runs (e.g., "packages/api/"). Omit to leave unchanged.'),isActive:r.z.boolean().optional().describe("Enable or disable the process"),setup:r.z.array(r.z.string()).optional().describe("New setup commands (replaces existing)"),commands:r.z.array(p).optional().describe("New test commands (replaces existing)"),verifyAcceptanceCriteria:r.z.boolean().optional().describe("When true, auto-tester verifies request acceptance criteria after running commands"),fingerprint:r.z.array(r.z.string()).optional().describe("Files whose content invalidates setup (replaces existing list)."),poolSize:r.z.number().int().min(1).max(8).optional().describe("Number of warm test worktrees in the pool (replaces existing).")}),exports.TestingReferenceSchema=r.z.object({}),exports.TestsSchema=r.z.object({operation:r.z.enum(["list","setup","run"]).describe('"list" to see registered test processes for this project. "setup" to spawn an interactive test-architect session that helps configure a process. "run" to fire an async test run for your current request \u2014 optional `process` picks one configured process (by name or id), optional `name` filters to one registered command. The call returns immediately and you receive a report on your next turn.'),process:r.z.string().optional().describe('Only used by `run`. Picks a single test process by name (case-insensitive) or id. Omit to run every active test process for this project. Use `operation: "list"` to see available process names.'),name:r.z.string().optional().describe("Only used by `run`. Filters execution to a single test command by name (matches a command name registered in the test process). Omit to run all required commands.")}),exports.ExecuteTestCommandSchema=r.z.object({processId:r.z.string().describe("Test process ID containing the command"),commandName:r.z.string().describe('Name of the test command to run, or "setup" to run all setup commands in sequence')}),exports.CommandsSchema=r.z.object({operation:r.z.enum(["run","list","remove","register","setup"]).default("run").describe('"run" to execute a command, "list" to see available commands, "register" to submit one or more commands for user approval (a single-item array works for one command; multiple items get bundled into a single batch approval notification), "remove" to delete one, "setup" to spawn the command-architect for an interactive setup interview (mirrors tests.setup)'),name:r.z.string().optional().describe('Command name (required for "run", "add", and "remove")'),args:r.z.string().optional().describe('Additional arguments appended to the base command (optional, for "run")'),grep:r.z.string().optional().describe('Filter output through grep (optional, for "run"). Pipes command output through grep -i with this pattern.'),command:r.z.string().optional().describe('Shell command to register (required for "add", e.g. "tsc --noEmit")'),description:r.z.string().optional().describe('What this command verifies. REQUIRED when operation is "add" \u2014 must articulate the command\'s purpose so the audit trail (added_by_session_id + description) is meaningful in the project commands UI.'),timeout:r.z.number().optional().describe('Timeout in seconds (optional, for "add", default 60)'),cwd:r.z.string().optional().describe('Working directory relative to project root (optional, for "add", e.g. "apps/web"). Omit to run at project root \u2014 use this for monorepos where the command lives in a subdir.'),context:r.z.string().optional().describe('Optional caller hint for the "setup" operation \u2014 short note about what the calling agent thinks the user needs (e.g. "specialist asked for npm run build with strict TS"). The architect treats this as a hint but still does its own discovery + user confirmation.'),commands:r.z.array(r.z.object({name:r.z.string().min(1).describe('Command name (e.g. "test:web")'),command:r.z.string().min(1).describe("Shell command to execute"),description:r.z.string().min(1).describe("What this command verifies"),cwd:r.z.string().optional().describe("Working directory relative to project root (omit for root)"),timeout:r.z.number().optional().describe("Timeout in seconds (default 60)")})).optional().describe('Batch of commands to register (required for "register", ignored otherwise). Each item must have name, command, and description. cwd is optional and supports monorepo subdirs.')}),exports.ReportTestResultsSchema=r.z.object({status:r.z.enum(["passed","failed","error"]).describe("Overall result"),results:r.z.object({commands:r.z.array(r.z.object({name:r.z.string().describe("Command name"),status:r.z.enum(["passed","failed","skipped","error"]).describe("Command result"),output:r.z.string().optional().describe("Relevant output snippet"),diagnosis:r.z.string().optional().describe("Why it failed, if applicable")})).describe("Per-command results"),summary:r.z.string().describe("Brief overall summary"),acceptanceCriteria:r.z.array(r.z.object({criterion:r.z.string().describe("The acceptance criterion text"),status:r.z.enum(["verified","unverified","unclear"]),evidence:r.z.string().describe("How verified, or why not")})).optional().describe("AC verification results, if applicable")}).describe("Structured test results")}),exports.SessionMessageOperationsSchema=r.z.object({operation:r.z.enum(["send","reply","list","get","offer-handoff"]),type:r.z.enum(["question","report"]).optional().describe("Message type to send (required for send)"),toSessionId:r.z.string().optional().describe('Target session ID, or "parent" to auto-resolve to parent session (omit for broadcast questions)'),questionType:r.z.enum(["free-form","alternatives"]).optional().describe('Type of question (required for send type="question")'),questionContent:r.z.object({question:r.z.string().min(1).describe("The question text"),context:r.z.string().optional().describe("Additional context"),options:r.z.array(r.z.object({id:r.z.string(),label:r.z.string(),description:r.z.string().optional()})).optional().describe("Options for alternatives questions"),allowMultiple:r.z.boolean().optional().describe("Allow selecting multiple options")}).optional().describe('Question content (required for send type="question")'),priority:r.z.enum(["low","normal","high"]).optional().describe("Question priority"),expiresInHours:r.z.number().optional().describe("Question expiry in hours"),status:r.z.enum(["success","partial","failure","blocked"]).optional().describe('Report status (required for send type="report")'),summary:r.z.string().optional().describe('Report summary (required for send type="report")'),details:r.z.string().optional().describe("Report details"),finish:r.z.boolean().optional().describe("Release request associations after report"),relatesTo:r.z.string().regex(/^I-[A-Za-z0-9]+-\d+$/,'relatesTo must be an instruction code like "I-abc12345-001"').optional().describe("Optional instruction code (I-...) this question or report relates to"),messageCode:r.z.string().optional().describe("Message code (required for reply and get operations)"),respondedBySessionId:r.z.string().optional().describe("Session ID answering the question. Optional \u2014 auto-filled from the caller's session (_meta.sessionId) when omitted; only pass explicitly to answer on behalf of a different session (e.g. UI passing 'user')."),text:r.z.string().optional().describe("Text answer for free-form questions"),selectedOptions:r.z.array(r.z.string()).optional().describe("Selected option IDs for alternatives"),notes:r.z.string().optional().describe("Additional notes"),list:r.z.object({sessionId:r.z.string().optional().describe("Filter by session ID (auto-discovered if omitted)"),messageType:r.z.enum(["question","report","instruction","all"]).default("all").describe("Filter by message type"),direction:r.z.enum(["incoming","outgoing","all"]).default("all"),status:r.z.enum(["pending","answered","expired","success","partial","failure","blocked","all"]).default("all").describe("Filter by status"),readStatus:r.z.enum(["unread","read","acknowledged","all"]).default("all").describe("Filter by read status (reports only)"),limit:r.z.number().min(1).max(100).default(50),offset:r.z.number().min(0).default(0)}).optional().describe('List filters (operation: "list" only)'),offerHandoff:r.z.object({summary:r.z.string().describe("Summary of what was planned/created"),requestIds:r.z.array(r.z.string()).describe("Request IDs that were created from the plan")}).optional().describe('Handoff offer details (operation: "offer-handoff" only)')}).refine((e=>"send"===e.operation?!!e.type:"reply"===e.operation?!!e.messageCode:"list"===e.operation||("get"===e.operation?!!e.messageCode:"offer-handoff"===e.operation)),{message:"Invalid operation data: send requires type, reply requires messageCode, get requires messageCode"}),exports.UpdateSpecializationSchema=r.z.object({specialization:r.z.string().min(1).max(500).describe("Your updated specialization summary \u2014 a concise description of your accumulated domain expertise"),specializationHeadline:r.z.string().min(1).max(80).optional().describe("Short tagline (\u226480 chars) summarising your domain at a glance \u2014 shown next to your name in the alchemist\u2019s specialist directory. Keep it current alongside the longer specialization.")}),exports.CommitToViewedSessionSchema=r.z.object({message:r.z.coerce.string().min(1).describe("The cleaned-up user message to post to the viewed session. Fix obvious dictation errors, add punctuation, but preserve the user's intent exactly.")})},6252(e,exports,t){"use strict"
|
|
3517
|
+
n&&!e[n.field]&&t.addIssue({code:"custom",message:`'${r}' operation requires '${n.field}' data. ${n.hint}`})})),exports.QuickWriteSchema=r.z.object({title:r.z.string().min(1,"Title is required"),description:r.z.string().min(1,"Description is required"),path:r.z.string().optional(),documentId:l.optional(),content:r.z.union([r.z.string(),r.z.array(r.z.string())]),format:r.z.enum(["text","json"]).optional(),append:r.z.boolean().optional()}).transform(d).refine(u,{message:"path or documentId required"}),exports.QuickReplaceSchema=r.z.object({title:r.z.string().min(1,"Title is required"),description:r.z.string().min(1,"Description is required"),operations:r.z.array(r.z.object({path:r.z.string().optional(),documentId:l.optional(),replacements:r.z.array(r.z.object({old:r.z.string().min(1),new:r.z.string(),match_mode:r.z.enum(["unique","all"]).optional()})).min(1),fuzzy_match:r.z.boolean().optional()}).transform(d).refine(u,{message:"path or documentId required"})).min(1),fuzzy_match:r.z.boolean().optional(),comment:r.z.string().min(1,"Comment describing the change is required")}),exports.QuickManageSchema=r.z.object({title:r.z.string().min(1,"Title is required"),description:r.z.string().min(1,"Description is required"),operations:r.z.array(r.z.object({operationType:r.z.enum(["create-directory","move-files","delete-files"]),createDirectory:r.z.object({path:r.z.string()}).optional(),moveFiles:r.z.object({moves:r.z.array(r.z.object({source:r.z.string(),destination:r.z.string()}))}).optional(),deleteFiles:r.z.object({targets:r.z.array(r.z.object({path:r.z.string().optional(),documentId:l.optional()}).transform(d).refine(u,{message:"path or documentId required"}))}).optional()})).min(1)}),exports.GenerateRequestJournalSchema=r.z.object({requestId:r.z.string().regex(/^req[_\d].+$/,"Invalid request ID format. Expected format: req_[26 chars] or req######")}),exports.MetaWorkflowListSchema=r.z.object({}),exports.MetaWorkflowGetSchema=r.z.object({workflowId:r.z.string().describe("Workflow ID to retrieve")}),exports.MetaWorkflowCreateSchema=r.z.object({name:r.z.string().min(1).describe("Unique name for the workflow"),shortName:r.z.string().min(1).max(10).describe("Short display name (required, max 10 chars)"),description:r.z.string().optional().describe("Description of what the workflow does"),documentation:r.z.string().optional().describe("Detailed documentation"),defaultAgent:r.z.string().optional().describe("Default agent template to use"),completionMode:r.z.enum(["auto-merge","ask-me","test-by-default","always-test"]).optional().describe("Testing axis: auto-merge (skip tests), ask-me (notify human on completion), test-by-default (tests run; opt-out allowed), always-test (tests required)"),reviewMode:r.z.enum(["auto-finalize","manual-review"]).optional().describe("Review axis: auto-finalize (server merges on pass/skip) or manual-review (human approves via UI)"),approvalMode:r.z.enum(["none","require-approval"]).optional().describe("Pre-work approval: none (default) or require-approval")}),exports.MetaWorkflowUpdateSchema=r.z.object({workflowId:r.z.string().describe("Workflow ID to update"),name:r.z.string().min(1).optional().describe("New name"),shortName:r.z.string().max(10).optional().describe("New short name (max 10 chars)"),description:r.z.string().optional().describe("New description"),documentation:r.z.string().optional().describe("New documentation"),defaultAgent:r.z.string().optional().describe("New default agent"),completionMode:r.z.enum(["auto-merge","ask-me","test-by-default","always-test"]).optional().describe("Testing axis"),reviewMode:r.z.enum(["auto-finalize","manual-review"]).optional().describe("Review axis"),approvalMode:r.z.enum(["none","require-approval"]).optional().describe("Pre-work approval: none (default) or require-approval")}),exports.MetaRecipeListSchema=r.z.object({}),exports.MetaRecipeGetSchema=r.z.object({recipeId:r.z.string().describe("Recipe ID to retrieve")}),exports.MetaRecipeCreateSchema=r.z.object({name:r.z.string().min(1).describe("Unique name for the recipe"),description:r.z.string().optional().describe("Description of what the recipe does"),documentation:r.z.string().optional().describe("Detailed documentation")}),exports.MetaRecipeAddHookSchema=r.z.object({recipeId:r.z.string().describe("Recipe ID to add the hook to"),hookId:r.z.string().describe("Hook template ID to add"),position:r.z.number().int().min(0).optional().describe("Position in the recipe (0-based, appended if omitted)")}),exports.MetaRecipeRemoveHookSchema=r.z.object({recipeId:r.z.string().describe("Recipe ID to remove the hook from"),hookId:r.z.string().describe("Hook template ID to remove")}),exports.MetaHookListSchema=r.z.object({}),exports.MetaHookCreateSchema=r.z.object({name:r.z.string().min(1).describe("Unique name for the hook"),description:r.z.string().optional().describe("Description of what the hook does"),eventType:r.z.string().describe("Event type that triggers this hook (e.g., session_idle, request_completed, custom:plan_ready)"),category:r.z.enum(["alchemy","session","message","editing","reading","file_management","documents","history","tool"]).default("session").describe("Hook category"),agent:r.z.string().describe("Agent template to execute when hook fires"),promptTemplate:r.z.string().describe("Prompt template with {{variable}} substitution"),condition:r.z.record(r.z.any()).optional().describe("Condition object for filtering when hook fires"),executionMode:r.z.enum(["same_session","sub_agent","background","notification","direct_report"]).default("background").describe("How to execute the hook"),timing:r.z.enum(["before","after"]).default("after").describe("When to fire relative to the event"),maxIterations:r.z.number().int().min(1).optional().describe("Maximum times to fire per session"),emitEvent:r.z.string().optional().describe("Custom event to emit on completion"),emitEventOnCondition:r.z.union([r.z.object({condition:r.z.object({field:r.z.string(),operator:r.z.enum(["contains","not_contains","equals","not_equals","matches","not_matches"]),value:r.z.string()}),event:r.z.string()}),r.z.array(r.z.object({condition:r.z.object({field:r.z.string(),operator:r.z.enum(["contains","not_contains","equals","not_equals","matches","not_matches"]),value:r.z.string()}),event:r.z.string()}))]).optional().describe("Conditional event emission based on output")}),exports.MetaWorkflowAddRecipeSchema=r.z.object({workflowId:r.z.string().describe("Workflow ID to add the recipe to"),recipeId:r.z.string().describe("Recipe ID to add"),position:r.z.number().int().min(0).optional().describe("Position in the workflow (0-based, appended if omitted)")}),exports.MetaWorkflowRemoveRecipeSchema=r.z.object({workflowId:r.z.string().describe("Workflow ID to remove the recipe from"),recipeId:r.z.string().describe("Recipe ID to remove")}),exports.MetaAgentListSchema=r.z.object({}),exports.MetaReferenceSchema=r.z.object({}),exports.TestingProcessListSchema=r.z.object({}),exports.TestingProcessGetSchema=r.z.object({processId:r.z.string().describe("Test process ID to retrieve")})
|
|
3518
|
+
const g=r.z.object({name:r.z.string().min(1).describe('Command name (e.g., "Build", "Unit Tests")'),command:r.z.string().min(1).describe('Shell command to run (e.g., "npm test")'),required:r.z.boolean().default(!0).describe("If true, failure blocks the request (default: true)"),timeout:r.z.number().int().min(10).max(3600).default(300).describe("Max execution time in seconds (default: 300)")})
|
|
3519
|
+
exports.TestingProcessCreateSchema=r.z.object({name:r.z.string().min(1).describe("Name for the test process"),description:r.z.string().optional().describe("Description of what this process verifies"),scope:r.z.string().optional().describe('Path prefix for monorepo scoping (e.g., "packages/api/"). Omit for global.'),setup:r.z.array(r.z.string()).optional().describe('Commands to prepare the environment (e.g., ["ln -s ../../node_modules node_modules"])'),commands:r.z.array(g).min(1).describe("Test commands to execute in order"),verifyAcceptanceCriteria:r.z.boolean().optional().describe("When true, auto-tester verifies request acceptance criteria after running commands"),fingerprint:r.z.array(r.z.string()).optional().describe('Files whose content invalidates setup. Setup commands re-run only when these files change between runs (e.g. ["package-lock.json"], ["Cargo.lock"], ["uv.lock", "poetry.lock"]). Polyglot repos list multiple. Omit / empty list = always re-run setup (existing behavior).'),poolSize:r.z.number().int().min(1).max(8).optional().describe("Number of warm test worktrees in the pool. Default 2. Set to 1 for languages with very large build artifacts (Rust target/, C++ build/). Higher values allow more parallel test runs at the cost of disk.")}),exports.TestingProcessDeleteSchema=r.z.object({processId:r.z.string().describe("Test process ID to delete")}),exports.TestingProcessUpdateSchema=r.z.object({processId:r.z.string().describe("Test process ID to update"),name:r.z.string().min(1).optional().describe("New name"),description:r.z.string().optional().describe("New description"),scope:r.z.string().optional().describe('New scope to limit when this process runs (e.g., "packages/api/"). Omit to leave unchanged.'),isActive:r.z.boolean().optional().describe("Enable or disable the process"),setup:r.z.array(r.z.string()).optional().describe("New setup commands (replaces existing)"),commands:r.z.array(g).optional().describe("New test commands (replaces existing)"),verifyAcceptanceCriteria:r.z.boolean().optional().describe("When true, auto-tester verifies request acceptance criteria after running commands"),fingerprint:r.z.array(r.z.string()).optional().describe("Files whose content invalidates setup (replaces existing list)."),poolSize:r.z.number().int().min(1).max(8).optional().describe("Number of warm test worktrees in the pool (replaces existing).")}),exports.TestingReferenceSchema=r.z.object({}),exports.TestsSchema=r.z.object({operation:r.z.enum(["list","setup","run"]).describe('"list" to see registered test processes for this project. "setup" to spawn an interactive test-architect session that helps configure a process. "run" to fire an async test run for your current request \u2014 optional `process` picks one configured process (by name or id), optional `name` filters to one registered command. The call returns immediately and you receive a report on your next turn.'),process:r.z.string().optional().describe('Only used by `run`. Picks a single test process by name (case-insensitive) or id. Omit to run every active test process for this project. Use `operation: "list"` to see available process names.'),name:r.z.string().optional().describe("Only used by `run`. Filters execution to a single test command by name (matches a command name registered in the test process). Omit to run all required commands.")}),exports.ExecuteTestCommandSchema=r.z.object({processId:r.z.string().describe("Test process ID containing the command"),commandName:r.z.string().describe('Name of the test command to run, or "setup" to run all setup commands in sequence')}),exports.CommandsSchema=r.z.object({operation:r.z.enum(["run","list","remove","register","setup"]).default("run").describe('"run" to execute a command, "list" to see available commands, "register" to submit one or more commands for user approval (a single-item array works for one command; multiple items get bundled into a single batch approval notification), "remove" to delete one, "setup" to spawn the command-architect for an interactive setup interview (mirrors tests.setup)'),name:r.z.string().optional().describe('Command name (required for "run", "add", and "remove")'),args:r.z.string().optional().describe('Additional arguments appended to the base command (optional, for "run")'),grep:r.z.string().optional().describe('Filter output through grep (optional, for "run"). Pipes command output through grep -i with this pattern.'),command:r.z.string().optional().describe('Shell command to register (required for "add", e.g. "tsc --noEmit")'),description:r.z.string().optional().describe('What this command verifies. REQUIRED when operation is "add" \u2014 must articulate the command\'s purpose so the audit trail (added_by_session_id + description) is meaningful in the project commands UI.'),timeout:r.z.number().optional().describe('Timeout in seconds (optional, for "add", default 60)'),cwd:r.z.string().optional().describe('Working directory relative to project root (optional, for "add", e.g. "apps/web"). Omit to run at project root \u2014 use this for monorepos where the command lives in a subdir.'),context:r.z.string().optional().describe('Optional caller hint for the "setup" operation \u2014 short note about what the calling agent thinks the user needs (e.g. "specialist asked for npm run build with strict TS"). The architect treats this as a hint but still does its own discovery + user confirmation.'),commands:r.z.array(r.z.object({name:r.z.string().min(1).describe('Command name (e.g. "test:web")'),command:r.z.string().min(1).describe("Shell command to execute"),description:r.z.string().min(1).describe("What this command verifies"),cwd:r.z.string().optional().describe("Working directory relative to project root (omit for root)"),timeout:r.z.number().optional().describe("Timeout in seconds (default 60)")})).optional().describe('Batch of commands to register (required for "register", ignored otherwise). Each item must have name, command, and description. cwd is optional and supports monorepo subdirs.')}),exports.ReportTestResultsSchema=r.z.object({status:r.z.enum(["passed","failed","error"]).describe("Overall result"),results:r.z.object({commands:r.z.array(r.z.object({name:r.z.string().describe("Command name"),status:r.z.enum(["passed","failed","skipped","error"]).describe("Command result"),output:r.z.string().optional().describe("Relevant output snippet"),diagnosis:r.z.string().optional().describe("Why it failed, if applicable")})).describe("Per-command results"),summary:r.z.string().describe("Brief overall summary"),acceptanceCriteria:r.z.array(r.z.object({criterion:r.z.string().describe("The acceptance criterion text"),status:r.z.enum(["verified","unverified","unclear"]),evidence:r.z.string().describe("How verified, or why not")})).optional().describe("AC verification results, if applicable")}).describe("Structured test results")}),exports.SessionMessageOperationsSchema=r.z.object({operation:r.z.enum(["send","reply","list","get","offer-handoff"]),type:r.z.enum(["question","report"]).optional().describe("Message type to send (required for send)"),toSessionId:r.z.string().optional().describe('Target session ID, or "parent" to auto-resolve to parent session (omit for broadcast questions)'),questionType:r.z.enum(["free-form","alternatives"]).optional().describe('Type of question (required for send type="question")'),questionContent:r.z.object({question:r.z.string().min(1).describe("The question text"),context:r.z.string().optional().describe("Additional context"),options:r.z.array(r.z.object({id:r.z.string(),label:r.z.string(),description:r.z.string().optional()})).optional().describe("Options for alternatives questions"),allowMultiple:r.z.boolean().optional().describe("Allow selecting multiple options")}).optional().describe('Question content (required for send type="question")'),priority:r.z.enum(["low","normal","high"]).optional().describe("Question priority"),expiresInHours:r.z.number().optional().describe("Question expiry in hours"),status:r.z.enum(["success","partial","failure","blocked"]).optional().describe('Report status (required for send type="report")'),summary:r.z.string().optional().describe('Report summary (required for send type="report")'),details:r.z.string().optional().describe("Report details"),finish:r.z.boolean().optional().describe("Release request associations after report"),relatesTo:r.z.string().regex(/^I-[A-Za-z0-9]+-\d+$/,'relatesTo must be an instruction code like "I-abc12345-001"').optional().describe("Optional instruction code (I-...) this question or report relates to"),messageCode:r.z.string().optional().describe("Message code (required for reply and get operations)"),respondedBySessionId:r.z.string().optional().describe("Session ID answering the question. Optional \u2014 auto-filled from the caller's session (_meta.sessionId) when omitted; only pass explicitly to answer on behalf of a different session (e.g. UI passing 'user')."),text:r.z.string().optional().describe("Text answer for free-form questions"),selectedOptions:r.z.array(r.z.string()).optional().describe("Selected option IDs for alternatives"),notes:r.z.string().optional().describe("Additional notes"),list:r.z.object({sessionId:r.z.string().optional().describe("Filter by session ID (auto-discovered if omitted)"),messageType:r.z.enum(["question","report","instruction","all"]).default("all").describe("Filter by message type"),direction:r.z.enum(["incoming","outgoing","all"]).default("all"),status:r.z.enum(["pending","answered","expired","success","partial","failure","blocked","all"]).default("all").describe("Filter by status"),readStatus:r.z.enum(["unread","read","acknowledged","all"]).default("all").describe("Filter by read status (reports only)"),limit:r.z.number().min(1).max(100).default(50),offset:r.z.number().min(0).default(0)}).optional().describe('List filters (operation: "list" only)'),offerHandoff:r.z.object({summary:r.z.string().describe("Summary of what was planned/created"),requestIds:r.z.array(r.z.string()).describe("Request IDs that were created from the plan")}).optional().describe('Handoff offer details (operation: "offer-handoff" only)')}).refine((e=>"send"===e.operation?!!e.type:"reply"===e.operation?!!e.messageCode:"list"===e.operation||("get"===e.operation?!!e.messageCode:"offer-handoff"===e.operation)),{message:"Invalid operation data: send requires type, reply requires messageCode, get requires messageCode"}),exports.UpdateSpecializationSchema=r.z.object({specialization:r.z.string().min(1).max(500).describe("Your updated specialization summary \u2014 a concise description of your accumulated domain expertise"),specializationHeadline:r.z.string().min(1).max(80).optional().describe("Short tagline (\u226480 chars) summarising your domain at a glance \u2014 shown next to your name in the alchemist\u2019s specialist directory. Keep it current alongside the longer specialization.")}),exports.CommitToViewedSessionSchema=r.z.object({message:r.z.coerce.string().min(1).describe("The cleaned-up user message to post to the viewed session. Fix obvious dictation errors, add punctuation, but preserve the user's intent exactly.")})},6252(e,exports,t){"use strict"
|
|
3475
3520
|
Object.defineProperty(exports,"__esModule",{value:!0}),exports.def=void 0
|
|
3476
3521
|
const r=t(6183),n=t(405)
|
|
3477
|
-
exports.def={name:"plan_write",description:"Create and modify project plans (
|
|
3522
|
+
exports.def={name:"plan_write",description:"Create and modify project plans. Also supports metadata updates on existing Quest documents (quests are created via the UI flow at /quests/new, not through this tool).\n\nOperations:\n\u2022 create - Create a new Plan document. Pass name + content. Quest metadata fields (criteria, tickIntervalSeconds, maxInFlight, maxPerDay, minIterations, status, completionMode) are not allowed on create.\n\u2022 update - Update plan content or quest metadata. For Quest documents, accepts criteria / tickIntervalSeconds / maxInFlight / maxPerDay / minIterations / status (open|pending_review|closed) / completionMode (auto-close|audit-then-pending|never-close). The LLM cannot set status='closed' directly \u2014 only the user closes a quest; the LLM may set status='pending_review' to pause ticks for user adjudication.\n\u2022 append - Append content to an existing plan\n\u2022 replace - Find and replace text within a plan\n\u2022 create-snapshot - Create a version snapshot\n\u2022 restore - Restore to a previous version\n\u2022 set-active - Set a plan as the project's active plan",schema:r.PlanWriteSchema,annotations:{title:"Plan Write",readOnlyHint:!1,destructiveHint:!1},handler(e,t){return(0,n.handlePlanWrite)(e,t.context,t.apiClient,t.logger,t.metrics,t.mcpServer,t.cliOrigin)}}},6261(module){"use strict"
|
|
3478
3523
|
module.exports=require("events")},6285(e,exports,t){"use strict"
|
|
3479
3524
|
Object.defineProperty(exports,"__esModule",{value:!0}),exports.handleSpecialistOps=async function(e,d,u,h,p,g){const m=u.child({tool:"specialist_ops"}),f=h.startTimer("tool_execution_time")
|
|
3480
3525
|
try{const u=e,{operation:y,sessionId:w}=u
|
|
@@ -3611,51 +3656,51 @@ const{taskId:q}=T
|
|
|
3611
3656
|
if(y.info("Inserting lines into files and documents",{taskId:q,operationCount:_.length,comment:E}),!_||0===_.length)throw new d.ValidationError("At least one operation is required")
|
|
3612
3657
|
const P=_.filter((e=>e.path)),j=_.filter((e=>e.documentId))
|
|
3613
3658
|
y.info("Operation breakdown",{fileOperations:P.length,documentOperations:j.length})
|
|
3614
|
-
const
|
|
3659
|
+
const x=[]
|
|
3615
3660
|
for(const e of P){const{normalizedPath:t,fullPath:r}=l.validateAndNormalizePath(e.path,n)
|
|
3616
|
-
|
|
3661
|
+
x.push({type:"file",path:t,fullPath:r,insertions:e.insertions})}const R=[]
|
|
3617
3662
|
if(j.length>0&&!n.documentFileManager)throw Error("Document file manager not available - cannot process document operations")
|
|
3618
|
-
for(const e of j)
|
|
3619
|
-
if(
|
|
3663
|
+
for(const e of j)R.push({type:"document",documentId:e.documentId,insertions:e.insertions})
|
|
3664
|
+
if(R.length>0&&n.apiClient){const e=R.map((e=>e.documentId))
|
|
3620
3665
|
try{await(0,p.ensureDocumentsNotLocked)(e,n.apiClient,y,m,"insert-lines-documents")}catch(e){if(e instanceof d.ValidationError)return{content:[{type:"text",text:e.message}],isError:!0}
|
|
3621
3666
|
throw e}}k=l.FileOperationPhase.TASK_VALIDATION,m.incrementCounter("insert_lines_phase",1,{phase:k})
|
|
3622
|
-
const M=
|
|
3667
|
+
const M=x.length>0?x[0].path:"document-operation",O=await l.validateTaskId(q,M,o,y,m,v.metricsPrefix),$=O?.requestId
|
|
3623
3668
|
let D=null
|
|
3624
|
-
|
|
3669
|
+
x.length>0&&$&&(D=await l.validateWorkItemStates(q,x[0].path,o,i,n,y,m,v.metricsPrefix))
|
|
3625
3670
|
let A={taskPromoted:!1,requestPromoted:!1}
|
|
3626
|
-
|
|
3671
|
+
x.length>0&&$&&D&&(A=await l.autoPromoteTaskStatus(q,O.status,$,D.request?.status,x[0].path,o,i,y,m,v.metricsPrefix),A.taskPromoted&&y.info("Auto-promoted task to in_progress for insert-lines operation",{taskId:q,requestId:$,previousStatus:O.status,newStatus:A.newTaskStatus,triggeringOperation:"insert-lines"}))
|
|
3627
3672
|
const F=await l.ensureCorrectWorkspaceContext({taskPromoted:A.taskPromoted,requestId:$,context:n,operation:"insert-lines",logger:y,metrics:m,metricsPrefix:v.metricsPrefix})
|
|
3628
3673
|
if(!F.success)throw Error(F.error)
|
|
3629
|
-
if(
|
|
3630
|
-
for(let e=0;e<
|
|
3631
|
-
|
|
3674
|
+
if(x.length>0){y.debug("Re-validating file paths with correct workspace context",{operationCount:x.length,workspaceBasePath:n.workspaceManager?.getCurrentContext(n.currentSessionId).basePath})
|
|
3675
|
+
for(let e=0;e<x.length;e++){const t=x[e],r=P[e],{normalizedPath:o,fullPath:s}=l.validateAndNormalizePath(r.path,n)
|
|
3676
|
+
x[e]={...t,path:o,fullPath:s}}}if(R.length>0&&$)try{await(0,u.validateRequestStatusForDocumentOperation)($,i,y,m,"insert-lines-document")}catch(e){if(e instanceof d.ValidationError)return{content:[{type:"text",text:e.message}],isError:!0}
|
|
3632
3677
|
throw e}k=l.FileOperationPhase.RECORD_CREATION,m.incrementCounter("insert_lines_phase",1,{phase:k})
|
|
3633
|
-
const N=[...
|
|
3634
|
-
if(b=z,I=z,k=v.fileOperationPhase,m.incrementCounter("insert_lines_phase",1,{phase:k}),
|
|
3678
|
+
const N=[...x.map((e=>({type:"file",path:e.path,insertions:e.insertions}))),...R.map((e=>({type:"document",documentId:e.documentId,insertions:e.insertions})))],{toolRecordId:z}=await l.createFileOperationRecords(q,$,n.projectId,v.recordType,M,{operationCount:_.length,fileOperations:x.length,documentOperations:R.length,operations:N,userComment:E},o,s,y,m,v.metricsPrefix,f)
|
|
3679
|
+
if(b=z,I=z,k=v.fileOperationPhase,m.incrementCounter("insert_lines_phase",1,{phase:k}),x.length>0&&n.git)try{y.debug("[INSERT-LINES] Checking for user changes before insert operations")
|
|
3635
3680
|
const e=await(0,h.commitUserChangesBeforeToolOperation)(n.git,"insert-lines",{requestId:$,taskId:q,workspaceManager:n.workspaceManager},y,m)
|
|
3636
|
-
e.userChangesCommitted&&(y.debug("[INSERT-LINES] User changes committed before insert operations",{commitHash:e.commitHash?.substring(0,8),filesCommitted:e.filesCommitted}),y.info("User changes committed before insert-lines operation",{taskId:q,fileOperationsCount:
|
|
3681
|
+
e.userChangesCommitted&&(y.debug("[INSERT-LINES] User changes committed before insert operations",{commitHash:e.commitHash?.substring(0,8),filesCommitted:e.filesCommitted}),y.info("User changes committed before insert-lines operation",{taskId:q,fileOperationsCount:x.length,userCommitHash:e.commitHash?.substring(0,8),userFilesCommitted:e.filesCommitted}))}catch(e){y.debug("[INSERT-LINES] Pre-tool commit failed, continuing with insertions",{error:e instanceof Error?e.message:e+""}),y.warn("Pre-tool user changes commit failed, continuing with insert operation",{taskId:q,fileOperationsCount:x.length,error:e instanceof Error?e.message:e+""})}y.debug("[INSERT-LINES] Proceeding with file operations",{fileCount:x.length})
|
|
3637
3682
|
const L=[]
|
|
3638
3683
|
let H=0,B=0,U=0
|
|
3639
|
-
for(const e of
|
|
3684
|
+
for(const e of x){const t={type:"file",path:e.path,success:!1,insertions:[],successfulInsertions:0,failedInsertions:0,totalLinesAdded:0}
|
|
3640
3685
|
try{if(await c.default.access(e.fullPath),!(await c.default.stat(e.fullPath)).isFile())throw Error("Path is not a file: "+e.path)
|
|
3641
3686
|
const n=await c.default.readFile(e.fullPath,"utf8"),{newContent:o,results:s}=await r(n,e.insertions)
|
|
3642
|
-
t.insertions=s,t.successfulInsertions=s.filter((e=>e.success)).length,t.failedInsertions=s.filter((e=>!e.success)).length,t.totalLinesAdded=s.filter((e=>e.success)).reduce(((e,t)=>e+(t.linesAdded||0)),0),o!==n&&t.successfulInsertions>0?(await c.default.writeFile(e.fullPath,o,"utf8"),t.success=!0,U++,y.info("File updated successfully",{path:e.path,successfulInsertions:t.successfulInsertions,failedInsertions:t.failedInsertions,linesAdded:t.totalLinesAdded})):0===t.failedInsertions&&(t.success=!0),H+=t.failedInsertions,B+=t.totalLinesAdded}catch(r){t.error=(0,g.getErrorMessage)(r),t.failedInsertions=e.insertions.length,H+=t.failedInsertions,y.error("File operation failed",{path:e.path,error:t.error})}L.push(t)}for(const e of
|
|
3687
|
+
t.insertions=s,t.successfulInsertions=s.filter((e=>e.success)).length,t.failedInsertions=s.filter((e=>!e.success)).length,t.totalLinesAdded=s.filter((e=>e.success)).reduce(((e,t)=>e+(t.linesAdded||0)),0),o!==n&&t.successfulInsertions>0?(await c.default.writeFile(e.fullPath,o,"utf8"),t.success=!0,U++,y.info("File updated successfully",{path:e.path,successfulInsertions:t.successfulInsertions,failedInsertions:t.failedInsertions,linesAdded:t.totalLinesAdded})):0===t.failedInsertions&&(t.success=!0),H+=t.failedInsertions,B+=t.totalLinesAdded}catch(r){t.error=(0,g.getErrorMessage)(r),t.failedInsertions=e.insertions.length,H+=t.failedInsertions,y.error("File operation failed",{path:e.path,error:t.error})}L.push(t)}for(const e of R){const t={type:"document",documentId:e.documentId,success:!1,insertions:[],successfulInsertions:0,failedInsertions:0,totalLinesAdded:0}
|
|
3643
3688
|
try{const o=await n.documentFileManager.getDocumentAsFile(e.documentId),s=n.documentFileManager.getCachedDocumentInfo(e.documentId)
|
|
3644
3689
|
t.filename=s?.filename
|
|
3645
3690
|
const i=await c.default.readFile(o,"utf8"),{newContent:a,results:l}=await r(i,e.insertions)
|
|
3646
|
-
t.insertions=l,t.successfulInsertions=l.filter((e=>e.success)).length,t.failedInsertions=l.filter((e=>!e.success)).length,t.totalLinesAdded=l.filter((e=>e.success)).reduce(((e,t)=>e+(t.linesAdded||0)),0),a!==i&&t.successfulInsertions>0?(await c.default.writeFile(o,a,"utf8"),n.documentFileManager.markForSync(e.documentId),t.success=!0,U++,y.info("Document updated successfully",{documentId:e.documentId,filename:t.filename,successfulInsertions:t.successfulInsertions,failedInsertions:t.failedInsertions,linesAdded:t.totalLinesAdded})):0===t.failedInsertions&&(t.success=!0),H+=t.failedInsertions,B+=t.totalLinesAdded}catch(r){t.error=(0,g.getErrorMessage)(r),t.failedInsertions=e.insertions.length,H+=t.failedInsertions,y.error("Document operation failed",{documentId:e.documentId,error:t.error})}L.push(t)}if(
|
|
3647
|
-
t?.success&&await n.documentFileManager.syncDocument(e.documentId)}}catch(e){y.warn("Some documents may not have synced properly",{error:e})}const G=await l.handleMultiFileGitCommit(q,
|
|
3648
|
-
try{await s.updateToolRecord(I,{metadata:{path:
|
|
3691
|
+
t.insertions=l,t.successfulInsertions=l.filter((e=>e.success)).length,t.failedInsertions=l.filter((e=>!e.success)).length,t.totalLinesAdded=l.filter((e=>e.success)).reduce(((e,t)=>e+(t.linesAdded||0)),0),a!==i&&t.successfulInsertions>0?(await c.default.writeFile(o,a,"utf8"),n.documentFileManager.markForSync(e.documentId),t.success=!0,U++,y.info("Document updated successfully",{documentId:e.documentId,filename:t.filename,successfulInsertions:t.successfulInsertions,failedInsertions:t.failedInsertions,linesAdded:t.totalLinesAdded})):0===t.failedInsertions&&(t.success=!0),H+=t.failedInsertions,B+=t.totalLinesAdded}catch(r){t.error=(0,g.getErrorMessage)(r),t.failedInsertions=e.insertions.length,H+=t.failedInsertions,y.error("Document operation failed",{documentId:e.documentId,error:t.error})}L.push(t)}if(R.length>0)try{for(const e of R){const t=L.find((t=>t.documentId===e.documentId))
|
|
3692
|
+
t?.success&&await n.documentFileManager.syncDocument(e.documentId)}}catch(e){y.warn("Some documents may not have synced properly",{error:e})}const G=await l.handleMultiFileGitCommit(q,x,L,U,{operationType:"Insert lines",toolRecordId:I,successField:"successfulInsertions",logger:y,metrics:m,metricsPrefix:"insert_lines"},n),W=l.processMultiFileOperationResults(L,"successfulInsertions"),{successfulOperations:V,failedOperations:Q,totalSuccessfulChanges:K,overallSuccess:J,successfulFiles:Y,failedFiles:Z}=W
|
|
3693
|
+
try{await s.updateToolRecord(I,{metadata:{path:x.length>0?x[0].path:"document:"+R[0]?.documentId,status:J?"completed":"failed",error:J?void 0:Q+" operations failed",totalOperations:L.length,successfulFiles:Y,failedFiles:Z,operations:N,totalSuccessfulInsertions:K,totalFailedInsertions:H,totalLinesAdded:B,operationsWithChanges:U,processingTime:Date.now()-w,userComment:E,...x.length>0&&G.success&&G.commitHash&&{commitHash:G.commitHash,previousCommitHash:G.previousCommitHash||void 0}},note:J?`Line insertion completed: ${V}/${L.length} operations successful${x.length>0?" (committed to git)":""}`:`Line insertion partially failed: ${Q}/${L.length} operations failed`})}catch(e){y.warn("Failed to update tool record",{recordError:e})}let X="## Line Insertion Results\n\n"
|
|
3649
3694
|
if(n.workspaceManager){const e=n.workspaceManager.getCurrentContext(n.currentSessionId)
|
|
3650
|
-
e.permanentBranch||(X+=`**Branch:** \`${e.branchName}\`\n\n`)}if(X+="**Summary:**\n",X+=`- **Files processed:** ${V+
|
|
3695
|
+
e.permanentBranch||(X+=`**Branch:** \`${e.branchName}\`\n\n`)}if(X+="**Summary:**\n",X+=`- **Files processed:** ${V+Q}\n`,X+=`- **Successful operations:** ${V}\n`,X+=`- **Failed operations:** ${Q}\n`,X+=`- **Total insertions:** ${K} successful, ${H} failed\n`,X+=`- **Total Lines Added:** ${B}\n`,X+="\n",G.success&&G.commitHash&&(X+="**Git Commit:**\n",X+=`- **Commit Hash:** ${G.commitHash.substring(0,8)}\n`,X+=`- **Files Committed:** ${G.filesCommitted.length}\n`,G.previousCommitHash&&(X+=`- **Previous Commit:** ${G.previousCommitHash.substring(0,8)}\n`),X+="\n"),1===L.length){const e=L[0]
|
|
3651
3696
|
if(X+=`**Operation:** ${e.success?"\u2705 Success":"\u274c Failed"}\n`,"file"===e.type?X+=`**File:** ${e.path}\n`:(X+="**Document:** "+e.documentId,e.filename&&(X+=` (${e.filename})`),X+="\n"),e.error?X+=`**Error:** ${e.error}\n`:(X+=`**Insertions:** ${e.successfulInsertions} successful`,e.failedInsertions>0&&(X+=`, ${e.failedInsertions} failed`),X+="\n",X+=`**Lines Added:** ${e.totalLinesAdded}\n`),e.insertions.some((e=>!e.success))){X+="**Failed Insertion Details:**\n"
|
|
3652
3697
|
for(const t of e.insertions.filter((e=>!e.success))){const e="between"===t.type?`between lines ${t.afterLine} and ${t.beforeLine}`:`${t.type} line ${t.line}`
|
|
3653
|
-
X+=`- ${t.type} insertion ${e}: ${t.error}\n`}}}else{X+="**Summary:**\n",X+=`- **Total Operations:** ${L.length}\n`,X+=`- **Successful:** ${V}\n`,X+=`- **Failed:** ${
|
|
3698
|
+
X+=`- ${t.type} insertion ${e}: ${t.error}\n`}}}else{X+="**Summary:**\n",X+=`- **Total Operations:** ${L.length}\n`,X+=`- **Successful:** ${V}\n`,X+=`- **Failed:** ${Q}\n`,X+=`- **Total Insertions:** ${K} successful, ${H} failed\n`,X+=`- **Total Lines Added:** ${B}\n\n`,X+="**Detailed Results:**\n\n"
|
|
3654
3699
|
for(const e of L){if("file"===e.type?X+=`### File: ${e.path}\n`:(X+="### Document: "+e.documentId,e.filename&&(X+=` (${e.filename})`),X+="\n"),X+=`- **Status:** ${e.success?"\u2705 Success":"\u274c Failed"}\n`,e.error?X+=`- **Error:** ${e.error}\n`:(X+=`- **Insertions:** ${e.successfulInsertions} successful`,e.failedInsertions>0&&(X+=`, ${e.failedInsertions} failed`),X+="\n",X+=`- **Lines Added:** ${e.totalLinesAdded}\n`),e.insertions.some((e=>!e.success))){X+="- **Failed Insertion Details:**\n"
|
|
3655
3700
|
for(const t of e.insertions.filter((e=>!e.success))){const e="between"===t.type?`between lines ${t.afterLine} and ${t.beforeLine}`:`${t.type} line ${t.line}`
|
|
3656
|
-
X+=` - ${t.type} insertion ${e}: ${t.error}\n`}}X+="\n"}}
|
|
3701
|
+
X+=` - ${t.type} insertion ${e}: ${t.error}\n`}}X+="\n"}}R.length>0&&(X+="\u{1f4c4} **Document Changes:** Modified documents have been automatically synced back to the tracking system.\n\n")
|
|
3657
3702
|
const ee=Date.now()-w
|
|
3658
|
-
return y.info("Insert lines operation completed",{duration:ee,success:
|
|
3703
|
+
return y.info("Insert lines operation completed",{duration:ee,success:J,totalOperations:L.length,successfulOperations:V,failedOperations:Q}),m.incrementCounter("insert_lines_total",1,{success:J}),{content:[{type:"text",text:X}],isError:!J}}catch(t){const r=Date.now()-w
|
|
3659
3704
|
if(y.error("Insert lines operation failed",{error:t instanceof Error?t.stack:t+"",duration:r,phase:k}),I)try{await s.updateToolRecord(I,{metadata:{path:e?.operations?.[0]?.path||e?.operations?.[0]?.documentId,status:"failed",error:(0,g.getErrorMessage)(t),phase:k,duration:r,userComment:e?.comment},note:"Line insertion failed: "+(0,g.getErrorMessage)(t)})}catch(e){}return m.incrementCounter("insert_lines_errors",1,{phase:k}),{content:[{type:"text",text:"\u274c **Insert Lines Failed:** "+(0,g.getErrorMessage)(t)}],isError:!0}}}
|
|
3660
3705
|
const c=a(t(1943)),l=i(t(5967)),d=t(9860),u=t(5003),h=t(7478),p=t(9949),g=t(8824),m=t(3255)},6539(e,exports,t){"use strict"
|
|
3661
3706
|
Object.defineProperty(exports,"__esModule",{value:!0}),exports.ClientFactory=void 0
|
|
@@ -3680,12 +3725,12 @@ if(I.registerClient(j),!w.alchemyPath)throw Error("alchemyPath is required for P
|
|
|
3680
3725
|
try{f.info("Creating ProjectSynchronizer components")
|
|
3681
3726
|
const{ProjectRegistry,ProjectFileSystem,ProjectSynchronizer}=await t.e(478).then(t.bind(t,5478)),e=new ProjectRegistry(f),r=new ProjectFileSystem(f),n=new ProjectSynchronizer(f,e,new l.ProjectClientAdapter(_,f),r,{createRemoteProjects:!0})
|
|
3682
3727
|
_.setProjectSynchronizer(n),f.info("ProjectSynchronizer created and connected to ProjectClient")}catch(e){const t="Failed to create required ProjectSynchronizer components: "+(0,h.getErrorMessage)(e)
|
|
3683
|
-
throw f.error(t,{error:e instanceof Error?e.stack:e+""}),Error(t)}const
|
|
3684
|
-
f.info("API client initialized with specialized clients"),v?(
|
|
3685
|
-
const
|
|
3686
|
-
|
|
3687
|
-
const M=
|
|
3688
|
-
return v&&!M?(f.error("CRITICAL: ApiClient token was not set properly!"),
|
|
3728
|
+
throw f.error(t,{error:e instanceof Error?e.stack:e+""}),Error(t)}const x=new o.ApiClient(k,_,E,S,T,q,P,j,f)
|
|
3729
|
+
f.info("API client initialized with specialized clients"),v?(x.setAuthToken(v),f.info("Auth token set on ApiClient during creation",{hasToken:!0,tokenLength:v.length})):f.warn("No auth token available during ApiClient creation",{info:"Client will need to authenticate before making requests"})
|
|
3730
|
+
const R=I.verifyAllClients()
|
|
3731
|
+
R.success?f.info("Token consistency verified across all clients"):f.error(`Token inconsistency detected in ${R.failedClients.length} clients: ${R.failedClients.join(", ")}`)
|
|
3732
|
+
const M=x.getAuthToken()
|
|
3733
|
+
return v&&!M?(f.error("CRITICAL: ApiClient token was not set properly!"),x.setAuthToken(v)):M&&f.info("ApiClient token verified",{tokenLength:M.length,matches:M===v}),f.info("API client creation completed successfully"),x}}},6540(e,exports){"use strict"
|
|
3689
3734
|
var t
|
|
3690
3735
|
Object.defineProperty(exports,"__esModule",{value:!0}),exports.LogLevel=void 0,function(e){e.ERROR="error",e.WARN="warn",e.INFO="info",e.DEBUG="debug"}(t||(exports.LogLevel=t={}))},6552(e,exports,t){"use strict"
|
|
3691
3736
|
async function r(){const e=new o.StdioServerTransport,t=(0,l.setupParentProcessDetection)((()=>{b.info("Parent process gone or orphan detected. Shutting down."),process.exit(0)}))
|
|
@@ -3763,34 +3808,34 @@ try{const _=e,{operations:E,comment:S}=_,{enforceActiveTask:T}=await Promise.res
|
|
|
3763
3808
|
if("errorResult"in q)return q.errorResult
|
|
3764
3809
|
const{taskId:P}=q
|
|
3765
3810
|
if(w.info("Replacing lines in files and documents",{taskId:P,operationCount:E.length,comment:S}),!E||0===E.length)throw new d.ValidationError("At least one operation is required")
|
|
3766
|
-
const j=E.filter((e=>e.path)),
|
|
3767
|
-
w.info("Operation breakdown",{fileOperations:j.length,documentOperations:
|
|
3768
|
-
const
|
|
3811
|
+
const j=E.filter((e=>e.path)),x=E.filter((e=>e.documentId))
|
|
3812
|
+
w.info("Operation breakdown",{fileOperations:j.length,documentOperations:x.length})
|
|
3813
|
+
const R=[]
|
|
3769
3814
|
for(const e of j){const{normalizedPath:t,fullPath:r}=l.validateAndNormalizePath(e.path,n)
|
|
3770
|
-
|
|
3771
|
-
if(
|
|
3772
|
-
for(const e of
|
|
3815
|
+
R.push({type:"file",path:t,fullPath:r,replacements:e.replacements.map((e=>({lines:(0,f.parseLineSpec)(e.lines),content:e.content})))})}const M=[]
|
|
3816
|
+
if(x.length>0&&!n.documentFileManager)throw Error("Document file manager not available - cannot process document operations")
|
|
3817
|
+
for(const e of x)M.push({type:"document",documentId:e.documentId,replacements:e.replacements.map((e=>({lines:(0,f.parseLineSpec)(e.lines),content:e.content})))})
|
|
3773
3818
|
if(M.length>0&&n.apiClient){const e=M.map((e=>e.documentId))
|
|
3774
3819
|
try{await(0,p.ensureDocumentsNotLocked)(e,n.apiClient,w,m,"replace-lines-documents")}catch(e){if(e instanceof d.ValidationError)return{content:[{type:"text",text:e.message}],isError:!0}
|
|
3775
3820
|
throw e}}v=l.FileOperationPhase.TASK_VALIDATION,m.incrementCounter("replace_lines_phase",1,{phase:v})
|
|
3776
|
-
const O=
|
|
3821
|
+
const O=R.length>0?R[0].path:"document-operation",$=await l.validateTaskId(P,O,o,w,m,C.metricsPrefix),D=$?.requestId
|
|
3777
3822
|
let A=null
|
|
3778
|
-
|
|
3823
|
+
R.length>0&&D&&(A=await l.validateWorkItemStates(P,R[0].path,o,i,n,w,m,C.metricsPrefix))
|
|
3779
3824
|
let F={taskPromoted:!1,requestPromoted:!1}
|
|
3780
|
-
|
|
3825
|
+
R.length>0&&D&&A&&(F=await l.autoPromoteTaskStatus(P,$.status,D,A.request?.status,R[0].path,o,i,w,m,C.metricsPrefix),F.taskPromoted&&w.info("Auto-promoted task to in_progress for replace-lines operation",{taskId:P,requestId:D,previousStatus:$.status,newStatus:F.newTaskStatus,triggeringOperation:"replace-lines"}))
|
|
3781
3826
|
const N=await l.ensureCorrectWorkspaceContext({taskPromoted:F.taskPromoted,requestId:D,context:n,operation:"replace-lines",logger:w,metrics:m,metricsPrefix:C.metricsPrefix})
|
|
3782
3827
|
if(!N.success)throw Error(N.error)
|
|
3783
|
-
if(
|
|
3784
|
-
for(let e=0;e<
|
|
3785
|
-
|
|
3828
|
+
if(R.length>0){w.debug("Re-validating file paths with correct workspace context",{operationCount:R.length,workspaceBasePath:n.workspaceManager?.getCurrentContext(n.currentSessionId).basePath})
|
|
3829
|
+
for(let e=0;e<R.length;e++){const t=R[e],r=j[e],{normalizedPath:o,fullPath:s}=l.validateAndNormalizePath(r.path,n)
|
|
3830
|
+
R[e]={...t,path:o,fullPath:s}}}if(M.length>0&&D)try{await(0,u.validateRequestStatusForDocumentOperation)(D,i,w,m,"replace-lines-document")}catch(e){if(e instanceof d.ValidationError)return{content:[{type:"text",text:e.message}],isError:!0}
|
|
3786
3831
|
throw e}v=l.FileOperationPhase.RECORD_CREATION,m.incrementCounter("replace_lines_phase",1,{phase:v})
|
|
3787
|
-
const z=[...
|
|
3788
|
-
if(I=L,k=L,v=C.fileOperationPhase,m.incrementCounter("replace_lines_phase",1,{phase:v}),
|
|
3832
|
+
const z=[...R.map((e=>({type:"file",path:e.path,replacements:e.replacements}))),...M.map((e=>({type:"document",documentId:e.documentId,replacements:e.replacements})))],{toolRecordId:L}=await l.createFileOperationRecords(P,D,n.projectId,C.recordType,O,{operationCount:E.length,fileOperations:R.length,documentOperations:M.length,operations:z,userComment:S},o,s,w,m,C.metricsPrefix,y)
|
|
3833
|
+
if(I=L,k=L,v=C.fileOperationPhase,m.incrementCounter("replace_lines_phase",1,{phase:v}),R.length>0&&n.git)try{w.debug("[REPLACE-LINES] Checking for user changes before replace operations")
|
|
3789
3834
|
const e=await(0,h.commitUserChangesBeforeToolOperation)(n.git,"replace-lines",{requestId:D,taskId:P,workspaceManager:n.workspaceManager},w,m)
|
|
3790
|
-
e.userChangesCommitted&&(w.debug("[REPLACE-LINES] User changes committed before replace operations",{commitHash:e.commitHash?.substring(0,8),filesCommitted:e.filesCommitted}),w.info("User changes committed before replace-lines operation",{taskId:P,fileOperationsCount:
|
|
3835
|
+
e.userChangesCommitted&&(w.debug("[REPLACE-LINES] User changes committed before replace operations",{commitHash:e.commitHash?.substring(0,8),filesCommitted:e.filesCommitted}),w.info("User changes committed before replace-lines operation",{taskId:P,fileOperationsCount:R.length,userCommitHash:e.commitHash?.substring(0,8),userFilesCommitted:e.filesCommitted}))}catch(e){w.debug("[REPLACE-LINES] Pre-tool commit failed, continuing with replacements",{error:e instanceof Error?e.message:e+""}),w.warn("Pre-tool user changes commit failed, continuing with replace operation",{taskId:P,fileOperationsCount:R.length,error:e instanceof Error?e.message:e+""})}w.debug("[REPLACE-LINES] Proceeding with file operations",{fileCount:R.length})
|
|
3791
3836
|
const H=[]
|
|
3792
3837
|
let B=0,U=0,G=0,W=0
|
|
3793
|
-
for(const e of
|
|
3838
|
+
for(const e of R){const t={type:"file",path:e.path,success:!1,replacements:[],successfulReplacements:0,failedReplacements:0,totalLinesReplaced:0,totalLinesAdded:0}
|
|
3794
3839
|
try{if(await c.default.access(e.fullPath),!(await c.default.stat(e.fullPath)).isFile())throw Error("Path is not a file: "+e.path)
|
|
3795
3840
|
const n=await c.default.readFile(e.fullPath,"utf8"),{newContent:o,results:s}=await r(n,e.replacements)
|
|
3796
3841
|
t.replacements=s,t.successfulReplacements=s.filter((e=>e.success)).length,t.failedReplacements=s.filter((e=>!e.success)).length,t.totalLinesReplaced=s.filter((e=>e.success)).reduce(((e,t)=>e+(t.linesReplaced||0)),0),t.totalLinesAdded=s.filter((e=>e.success)).reduce(((e,t)=>e+(t.linesAdded||0)),0),o!==n&&t.successfulReplacements>0?(await c.default.writeFile(e.fullPath,o,"utf8"),t.success=!0,W++,w.info("File updated successfully",{path:e.path,successfulReplacements:t.successfulReplacements,failedReplacements:t.failedReplacements,linesReplaced:t.totalLinesReplaced,linesAdded:t.totalLinesAdded})):0===t.failedReplacements&&(t.success=!0),B+=t.failedReplacements,U+=t.totalLinesReplaced,G+=t.totalLinesAdded}catch(r){t.error=(0,g.getErrorMessage)(r),t.failedReplacements=e.replacements.length,B+=t.failedReplacements,w.error("File operation failed",{path:e.path,error:t.error})}H.push(t)}for(const e of M){const t={type:"document",documentId:e.documentId,success:!1,replacements:[],successfulReplacements:0,failedReplacements:0,totalLinesReplaced:0,totalLinesAdded:0}
|
|
@@ -3798,28 +3843,28 @@ try{const o=await n.documentFileManager.getDocumentAsFile(e.documentId),s=n.docu
|
|
|
3798
3843
|
t.filename=s?.filename
|
|
3799
3844
|
const i=await c.default.readFile(o,"utf8"),{newContent:a,results:l}=await r(i,e.replacements)
|
|
3800
3845
|
t.replacements=l,t.successfulReplacements=l.filter((e=>e.success)).length,t.failedReplacements=l.filter((e=>!e.success)).length,t.totalLinesReplaced=l.filter((e=>e.success)).reduce(((e,t)=>e+(t.linesReplaced||0)),0),t.totalLinesAdded=l.filter((e=>e.success)).reduce(((e,t)=>e+(t.linesAdded||0)),0),a!==i&&t.successfulReplacements>0?(await c.default.writeFile(o,a,"utf8"),n.documentFileManager.markForSync(e.documentId),t.success=!0,W++,w.info("Document updated successfully",{documentId:e.documentId,filename:t.filename,successfulReplacements:t.successfulReplacements,failedReplacements:t.failedReplacements,linesReplaced:t.totalLinesReplaced,linesAdded:t.totalLinesAdded})):0===t.failedReplacements&&(t.success=!0),B+=t.failedReplacements,U+=t.totalLinesReplaced,G+=t.totalLinesAdded}catch(r){t.error=(0,g.getErrorMessage)(r),t.failedReplacements=e.replacements.length,B+=t.failedReplacements,w.error("Document operation failed",{documentId:e.documentId,error:t.error})}H.push(t)}if(M.length>0)try{for(const e of M){const t=H.find((t=>t.documentId===e.documentId))
|
|
3801
|
-
t?.success&&await n.documentFileManager.syncDocument(e.documentId)}}catch(e){w.warn("Some documents may not have synced properly",{error:e})}const V=await l.handleMultiFileGitCommit(P,
|
|
3802
|
-
try{await s.updateToolRecord(k,{metadata:{path:
|
|
3846
|
+
t?.success&&await n.documentFileManager.syncDocument(e.documentId)}}catch(e){w.warn("Some documents may not have synced properly",{error:e})}const V=await l.handleMultiFileGitCommit(P,R,H,W,{operationType:"Replace lines",toolRecordId:k,successField:"successfulReplacements",logger:w,metrics:m,metricsPrefix:"replace_lines"},n),Q=l.processMultiFileOperationResults(H,"successfulReplacements"),{successfulOperations:K,failedOperations:J,totalSuccessfulChanges:Y,overallSuccess:Z,successfulFiles:X,failedFiles:ee}=Q
|
|
3847
|
+
try{await s.updateToolRecord(k,{metadata:{path:R.length>0?R[0].path:"document:"+M[0]?.documentId,status:Z?"completed":"failed",error:Z?void 0:J+" operations failed",totalOperations:H.length,successfulFiles:X,failedFiles:ee,operations:z,totalSuccessfulReplacements:Y,totalFailedReplacements:B,totalLinesReplaced:U,totalLinesAdded:G,operationsWithChanges:W,processingTime:Date.now()-b,userComment:S,...R.length>0&&V.success&&V.commitHash&&{commitHash:V.commitHash,previousCommitHash:V.previousCommitHash||void 0}},note:Z?`Line replacement completed: ${K}/${H.length} operations successful${R.length>0?" (committed to git)":""}`:`Line replacement partially failed: ${J}/${H.length} operations failed`})}catch(e){w.warn("Failed to update tool record",{recordError:e})}let te="## Line Replacement Results\n\n"
|
|
3803
3848
|
if(n.workspaceManager){const e=n.workspaceManager.getCurrentContext(n.currentSessionId)
|
|
3804
|
-
e.permanentBranch||(te+=`**Branch:** \`${e.branchName}\`\n\n`)}if(te+="**Summary:**\n",te+=`- **Files processed:** ${J
|
|
3849
|
+
e.permanentBranch||(te+=`**Branch:** \`${e.branchName}\`\n\n`)}if(te+="**Summary:**\n",te+=`- **Files processed:** ${K+J}\n`,te+=`- **Successful operations:** ${K}\n`,te+=`- **Failed operations:** ${J}\n`,te+=`- **Total replacements:** ${Y} successful, ${B} failed\n`,te+=`- **Total Lines Replaced:** ${U}\n`,G>0&&(te+=`- **Total Lines Added:** ${G}\n`),te+="\n",V.success&&V.commitHash&&(te+="**Git Commit:**\n",te+=`- **Commit Hash:** ${V.commitHash.substring(0,8)}\n`,te+=`- **Files Committed:** ${V.filesCommitted.length}\n`,V.previousCommitHash&&(te+=`- **Previous Commit:** ${V.previousCommitHash.substring(0,8)}\n`),te+="\n"),1===H.length){const e=H[0]
|
|
3805
3850
|
if(te+=`**Operation:** ${e.success?"\u2705 Success":"\u274c Failed"}\n`,"file"===e.type?te+=`**File:** ${e.path}\n`:(te+="**Document:** "+e.documentId,e.filename&&(te+=` (${e.filename})`),te+="\n"),e.error?te+=`**Error:** ${e.error}\n`:(te+=`**Replacements:** ${e.successfulReplacements} successful`,e.failedReplacements>0&&(te+=`, ${e.failedReplacements} failed`),te+="\n",te+=`**Lines Replaced:** ${e.totalLinesReplaced}\n`,e.totalLinesAdded>0&&(te+=`**Lines Added:** ${e.totalLinesAdded}\n`)),e.replacements.some((e=>!e.success))){te+="**Failed Replacement Details:**\n"
|
|
3806
|
-
for(const t of e.replacements.filter((e=>!e.success)))te+=`- Replace ${"number"==typeof t.lines?"line "+t.lines:Array.isArray(t.lines)?`lines [${t.lines.join(", ")}]`:`lines ${t.lines.start}-${t.lines.end}`}: ${t.error}\n`}}else{te+="**Summary:**\n",te+=`- **Total Operations:** ${H.length}\n`,te+=`- **Successful:** ${
|
|
3851
|
+
for(const t of e.replacements.filter((e=>!e.success)))te+=`- Replace ${"number"==typeof t.lines?"line "+t.lines:Array.isArray(t.lines)?`lines [${t.lines.join(", ")}]`:`lines ${t.lines.start}-${t.lines.end}`}: ${t.error}\n`}}else{te+="**Summary:**\n",te+=`- **Total Operations:** ${H.length}\n`,te+=`- **Successful:** ${K}\n`,te+=`- **Failed:** ${J}\n`,te+=`- **Total Replacements:** ${Y} successful, ${B} failed\n`,te+=`- **Total Lines Replaced:** ${U}\n`,G>0&&(te+=`- **Total Lines Added:** ${G}\n`),te+="\n",te+="**Detailed Results:**\n\n"
|
|
3807
3852
|
for(const e of H){if("file"===e.type?te+=`### File: ${e.path}\n`:(te+="### Document: "+e.documentId,e.filename&&(te+=` (${e.filename})`),te+="\n"),te+=`- **Status:** ${e.success?"\u2705 Success":"\u274c Failed"}\n`,e.error&&(te+=`- **Error:** ${e.error}\n`),te+=`- **Replacements:** ${e.successfulReplacements} successful`,e.failedReplacements>0&&(te+=`, ${e.failedReplacements} failed`),te+="\n",te+=`- **Lines Replaced:** ${e.totalLinesReplaced}\n`,e.totalLinesAdded>0&&(te+=`- **Lines Added:** ${e.totalLinesAdded}\n`),e.replacements.some((e=>!e.success))){te+="- **Failed Replacement Details:**\n"
|
|
3808
3853
|
for(const t of e.replacements.filter((e=>!e.success)))te+=` - Replace ${"number"==typeof t.lines?"line "+t.lines:Array.isArray(t.lines)?`lines [${t.lines.join(", ")}]`:`lines ${t.lines.start}-${t.lines.end}`}: ${t.error}\n`}te+="\n"}}M.length>0&&(te+="\u{1f4c4} **Document Changes:** Modified documents have been automatically synced back to the tracking system.\n\n")
|
|
3809
3854
|
const re=Date.now()-b
|
|
3810
|
-
return w.info("Replace lines operation completed",{duration:re,success:Z,totalOperations:H.length,successfulOperations:
|
|
3855
|
+
return w.info("Replace lines operation completed",{duration:re,success:Z,totalOperations:H.length,successfulOperations:K,failedOperations:J}),m.incrementCounter("replace_lines_total",1,{success:Z}),{content:[{type:"text",text:te}],isError:!Z}}catch(t){const r=Date.now()-b
|
|
3811
3856
|
if(w.error("Replace lines operation failed",{error:t instanceof Error?t.stack:t+"",duration:r,phase:v}),k)try{await s.updateToolRecord(k,{metadata:{path:e?.operations?.[0]?.path||e?.operations?.[0]?.documentId,status:"failed",error:(0,g.getErrorMessage)(t),phase:v,duration:r,userComment:e?.comment},note:"Line replacement failed: "+(0,g.getErrorMessage)(t)})}catch(e){}return m.incrementCounter("replace_lines_errors",1,{phase:v}),{content:[{type:"text",text:"\u274c **Replace Lines Failed:** "+(0,g.getErrorMessage)(t)}],isError:!0}}}
|
|
3812
3857
|
const c=a(t(1943)),l=i(t(5967)),d=t(9860),u=t(5003),h=t(7478),p=t(9949),g=t(8824),m=t(3255),f=t(9470)},6656(e,exports,t){"use strict"
|
|
3813
|
-
Object.defineProperty(exports,"__esModule",{value:!0}),exports.handleCreatePlan=async function(e,t,o,s,i,a
|
|
3814
|
-
try{const
|
|
3815
|
-
if(!
|
|
3816
|
-
const
|
|
3817
|
-
if(
|
|
3818
|
-
const
|
|
3819
|
-
if(
|
|
3820
|
-
|
|
3821
|
-
t&&!t.activePlanId&&(await e.updateProject(
|
|
3822
|
-
const r=t(8824)
|
|
3858
|
+
Object.defineProperty(exports,"__esModule",{value:!0}),exports.handleCreatePlan=async function(e,t,n,o,s,i,a){const c=o.child({tool:"plan_operations",operation:"create"})
|
|
3859
|
+
try{const o=t.projectId
|
|
3860
|
+
if(!o)return{content:[{type:"text",text:"\u274c No project context available. Please ensure project is initialized."}],isError:!0}
|
|
3861
|
+
const s=`PLAN-${e.name.replace(/\.md$/i,"")}.md`,i=n.getDocumentClient(),l=await i.listDocuments({type:"Plan",filename:s,limit:1,offset:0})
|
|
3862
|
+
if(l&&l.length>0)return{content:[{type:"text",text:`\u274c A plan with filename "${s}" already exists (${l[0].localId||l[0].id}). Choose a different name.`}],isError:!0}
|
|
3863
|
+
const d=await i.createDocument(void 0,{filename:s,content:e.content,type:"Plan",metadata:{isStub:!0},...a&&{cliOrigin:a}}),u=d.localId||d.id,h=d.id
|
|
3864
|
+
if(a?.sessionId)try{await n.proxyPost(`/api/projects/${o}/session-plan-associations`,{opencodeSessionId:a.sessionId,documentId:h})}catch(e){c.warn("Failed to create session-plan association",{error:(0,r.getErrorMessage)(e)})}let p=!1
|
|
3865
|
+
try{const e=n.getProjectClient(),t=await e.getProject(o)
|
|
3866
|
+
t&&!t.activePlanId&&(await e.updateProject(o,{activePlanId:h}),p=!0,c.info("Auto-set as active plan",{planId:u,projectId:o}))}catch(e){c.warn("Failed to auto-set active plan",{error:(0,r.getErrorMessage)(e)})}return c.info("Plan Created",{planId:u,filename:s}),{content:[{type:"text",text:`\u2705 **Plan Created**\n\n**Plan ID:** ${u}\n**Filename:** ${s}\n**Created:** `+new Date(d.createdAt).toLocaleString()+(p?"\n\n\u{1f4cc} _Automatically set as the active project plan._":"")}]}}catch(e){return c.error("Failed to create plan",{error:(0,r.getErrorMessage)(e)}),{content:[{type:"text",text:"\u274c **Failed to create plan:** "+(0,r.getErrorMessage)(e)}],isError:!0}}}
|
|
3867
|
+
const r=t(8824)},6688(e,exports,t){"use strict"
|
|
3823
3868
|
Object.defineProperty(exports,"__esModule",{value:!0}),exports.sessionIdentity=void 0
|
|
3824
3869
|
const r=t(9896),n=t(6928),o=t(3545)
|
|
3825
3870
|
exports.sessionIdentity=new class{constructor(){this.parentCache=new Map,this.sessionRequestCache=new Map}setIdentity(e){const t=this.identity
|
|
@@ -3904,9 +3949,9 @@ const f=r.getTaskClient(),y=r.getToolRecordClient(),w=t.projectId
|
|
|
3904
3949
|
let b
|
|
3905
3950
|
r.setProjectId(w)
|
|
3906
3951
|
try{const j=await f.getTask(g)
|
|
3907
|
-
s.info("Raw task response data",{responseDataType:typeof j,isArray:Array.isArray(j),hasData:null!=j,properties:j&&"object"==typeof j?Object.keys(j):[]}),b=(0,l.extractDataFromResponse)(j,{logger:s,operationName:"getTask",defaultValue:{id:g,title:"Unknown Task",status:"unknown",description:"No description available"}}),s.info("Found task: "+b.title)}catch(
|
|
3908
|
-
try{const
|
|
3909
|
-
if(s.info("Raw records response data",{responseDataType:typeof
|
|
3952
|
+
s.info("Raw task response data",{responseDataType:typeof j,isArray:Array.isArray(j),hasData:null!=j,properties:j&&"object"==typeof j?Object.keys(j):[]}),b=(0,l.extractDataFromResponse)(j,{logger:s,operationName:"getTask",defaultValue:{id:g,title:"Unknown Task",status:"unknown",description:"No description available"}}),s.info("Found task: "+b.title)}catch(x){s.warn("Could not fetch task information: "+(0,u.getErrorMessage)(x)),b={id:g,title:"Unknown Task",status:"unknown",description:"No description available"}}let I=[]
|
|
3953
|
+
try{const R=await y.getToolRecordsByTaskId(g)
|
|
3954
|
+
if(s.info("Raw records response data",{responseDataType:typeof R,isArray:Array.isArray(R),hasData:null!=R,properties:R&&"object"==typeof R?Object.keys(R):[]}),I=(0,l.extractArrayFromResponse)(R,{logger:s,operationName:"searchRecords",defaultValue:[]}),I.length>0&&s.info("First record summary:",{id:I[0].id,type:I[0].type,hasMetadata:!!I[0].metadata,hasCommitHash:!!I[0].metadata?.commitHash}),s.info(`Extracted ${I.length} records for task ${g}`),I.length>0){const M={}
|
|
3910
3955
|
I.forEach((e=>{M[e.type]=(M[e.type]||0)+1})),s.info("Record type distribution:",M)}}catch(O){s.warn("Error fetching records for task "+g,{error:(0,u.getErrorMessage)(O)}),I=[]}if(0===I.length)return p({success:!0,recordCount:0}),{content:[{type:"text",text:`No records found for task ${g}.`}]}
|
|
3911
3956
|
function k(e){const t=new Map,r=new Map,n=[]
|
|
3912
3957
|
for(const o of e)if("move-file"===o.type&&o.metadata){const e=o.metadata.source||o.metadata.oldPath,s=o.metadata.destination||o.metadata.newPath
|
|
@@ -3962,9 +4007,9 @@ const z=new Map
|
|
|
3962
4007
|
N.forEach((e=>{e.recordId&&e.record?.metadata?.status&&(z.has(e.recordId)||z.set(e.recordId,[]),z.get(e.recordId)?.push(e.record.metadata.status))})),z.forEach(((e,t)=>{s.info(`Record ${t} status updates: ${e.join(" -> ")}`)}))
|
|
3963
4008
|
const L=N.filter((e=>e.commitHash))
|
|
3964
4009
|
if(s.info(`Found ${L.length} records with commit hash for ${F}`),0===L.length){s.info(`No commit hashes found in record metadata for ${F}, trying git log`)
|
|
3965
|
-
try{if(t.git){const
|
|
3966
|
-
if(
|
|
3967
|
-
const Y=
|
|
4010
|
+
try{if(t.git){const K={file:F,n:10},J=await t.git.log(K)
|
|
4011
|
+
if(J&&J.all&&J.all.length>0){s.info(`Found ${J.all.length} commits for ${F} using git log`)
|
|
4012
|
+
const Y=J.all.map((e=>({filePath:F,recordId:"git-"+e.hash.substring(0,8),type:"git-commit",timestamp:new Date(e.date).toISOString(),commitHash:e.hash,status:"completed",record:{id:"git-"+e.hash.substring(0,8),type:"git-commit",content:e.message,createdAt:new Date(e.date).toISOString(),metadata:{commitHash:e.hash}}})))
|
|
3968
4013
|
if(Y.length>0){const Z=Y.length>1?Y[Y.length-1]:Y[0],X=Y[0],ee=1===Y.length
|
|
3969
4014
|
s.info(ee?`Using single git commit for ${F}: ${X.commitHash?X.commitHash.substring(0,8):"unknown"}`:`Using git commits for ${F}: ${Z.commitHash?Z.commitHash.substring(0,8):"unknown"} to ${X.commitHash?X.commitHash.substring(0,8):"unknown"}`)
|
|
3970
4015
|
let te=""
|
|
@@ -3984,33 +4029,33 @@ for(const pe of he)ue+=`+${pe}\n`
|
|
|
3984
4029
|
E.set(F,{firstChange:W,lastChange:B,hasDiff:!0,diffText:ue}),s.info(`Formatted new file content as diff, ${he.length} lines`)
|
|
3985
4030
|
continue}}catch(ge){s.warn("Error getting new file content for "+F,{error:(0,u.getErrorMessage)(ge)})}E.set(F,{firstChange:W,lastChange:B,hasDiff:!1,diffText:"Only one commit available for this file"})
|
|
3986
4031
|
continue}if(H.commitHash===B.commitHash&&G){if(U===H.commitHash){E.set(F,{firstChange:W,lastChange:B,hasDiff:!1,diffText:"No changes detected"})
|
|
3987
|
-
continue}s.info("Special case: First and last task commits are the same, but pre-task commit is different")}let V="",
|
|
3988
|
-
if(m||"pre-task"!==W.status){try{if(t.git){try{await t.git.show([`${B.commitHash}:${F}`])}catch(fe){s.warn(`File ${F} does not exist in commit ${B.commitHash}, might be deleted or moved`),V="File was deleted or moved from this location during the task",
|
|
4032
|
+
continue}s.info("Special case: First and last task commits are the same, but pre-task commit is different")}let V="",Q=!1
|
|
4033
|
+
if(m||"pre-task"!==W.status){try{if(t.git){try{await t.git.show([`${B.commitHash}:${F}`])}catch(fe){s.warn(`File ${F} does not exist in commit ${B.commitHash}, might be deleted or moved`),V="File was deleted or moved from this location during the task",Q=!0,E.set(F,{firstChange:W,lastChange:B,hasDiff:Q,diffText:V})
|
|
3989
4034
|
continue}let me
|
|
3990
|
-
if("pre-task"===W.status?(me=[`${W.commitHash}..${B.commitHash}`,"--",F],s.info(`Comparing pre-task commit with final commit: ${W.commitHash?W.commitHash.substring(0,8):"unknown"}..${B.commitHash?B.commitHash.substring(0,8):"unknown"} for ${F}`)):(me=["4b825dc642cb6eb9a060e54bf8d69288fbee4904.."+B.commitHash,"--",F],s.info(`File created during task, showing full file diff using empty tree object: ${B.commitHash?B.commitHash.substring(0,8):"unknown"} for ${F}`)),V=await t.git.diff(me),
|
|
4035
|
+
if("pre-task"===W.status?(me=[`${W.commitHash}..${B.commitHash}`,"--",F],s.info(`Comparing pre-task commit with final commit: ${W.commitHash?W.commitHash.substring(0,8):"unknown"}..${B.commitHash?B.commitHash.substring(0,8):"unknown"} for ${F}`)):(me=["4b825dc642cb6eb9a060e54bf8d69288fbee4904.."+B.commitHash,"--",F],s.info(`File created during task, showing full file diff using empty tree object: ${B.commitHash?B.commitHash.substring(0,8):"unknown"} for ${F}`)),V=await t.git.diff(me),Q=!!V&&V.trim().length>0,!Q&&W.commitHash!==B.commitHash){s.info("No diff found between commits but commits are different, trying direct file content comparison")
|
|
3991
4036
|
try{const ye=await t.git.show([`${W.commitHash}:${F}`]),we=await t.git.show([`${B.commitHash}:${F}`])
|
|
3992
|
-
if(ye!==we&&(
|
|
3993
|
-
Math.abs(be.length-Ie.length)>0&&(V+=`\n\nLine count changed: ${be.length} \u2192 ${Ie.length}`),ye.includes("\0")||we.includes("\0")?V+="\n\nBinary content detected - changes not displayed":ye.replace(/\s+/g,"")===we.replace(/\s+/g,"")&&(V+="\n\nWhitespace-only changes detected")}}catch(ke){s.warn("Error in direct file comparison: "+(ke instanceof Error?ke.message:ke+""))}}s.info(`Diff generation result for ${F}: hasDiff=${
|
|
4037
|
+
if(ye!==we&&(Q=!0,V="Changes detected through direct content comparison (not visible in standard diff)",m)){const be=ye.split("\n"),Ie=we.split("\n")
|
|
4038
|
+
Math.abs(be.length-Ie.length)>0&&(V+=`\n\nLine count changed: ${be.length} \u2192 ${Ie.length}`),ye.includes("\0")||we.includes("\0")?V+="\n\nBinary content detected - changes not displayed":ye.replace(/\s+/g,"")===we.replace(/\s+/g,"")&&(V+="\n\nWhitespace-only changes detected")}}catch(ke){s.warn("Error in direct file comparison: "+(ke instanceof Error?ke.message:ke+""))}}s.info(`Diff generation result for ${F}: hasDiff=${Q}, length=${V.length}`)}}catch(ve){if(s.warn("Error getting diff for "+F,{error:(0,u.getErrorMessage)(ve),firstCommit:H.commitHash||"unknown",lastCommit:B.commitHash||"unknown"}),V="Error getting diff: "+(0,u.getErrorMessage)(ve),"pre-task"!==H.status&&t.git)try{const Ce=[`${B.commitHash}:${F}`]
|
|
3994
4039
|
s.info(`Trying fallback to show file content using git show: ${B.commitHash?B.commitHash.substring(0,8):"unknown"}:${F}`)
|
|
3995
4040
|
const _e=await t.git.show(Ce)
|
|
3996
4041
|
if(_e&&_e.trim().length>0){if(m){let Ee=""
|
|
3997
4042
|
const Se=_e.split("\n")
|
|
3998
4043
|
for(const Te of Se)Ee+=`+${Te}\n`
|
|
3999
4044
|
V=Ee}else V="File created during this task. Content:\n"+_e
|
|
4000
|
-
|
|
4045
|
+
Q=!0,s.info("Fallback succeeded, got file content of length "+_e.length)}}catch(qe){s.warn("Fallback also failed for "+F,{error:qe instanceof Error?qe.message:qe+""})}}E.set(F,{firstChange:W,lastChange:B,hasDiff:Q,diffText:V||"No changes detected between commits"})}else Q=W.commitHash!==B.commitHash,V=Q?"File has changes":"No changes detected between commits",E.set(F,{firstChange:W,lastChange:B,hasDiff:Q,diffText:V})}let S=`# File Changes for Task: ${g}\n\n`
|
|
4001
4046
|
b&&"object"==typeof b&&(S+="## Task Information\n",S+=`- **Title**: ${b.title||"Unknown"}\n`,S+=`- **Status**: ${b.status||"Unknown"}\n`,S+=`- **Description**: ${b.description||"No description"}\n\n`)
|
|
4002
4047
|
const T=3e3
|
|
4003
4048
|
let q=0,P=!1
|
|
4004
4049
|
if(m){for(const Pe of E.values())Pe.hasDiff&&Pe.diffText&&(q+=Pe.diffText.split("\n").length)
|
|
4005
4050
|
P=q>T,s.info(`Total diff size: ${q} lines (limit: ${T} lines)`),s.info(`Diffs ${P?"will be limited":"will be shown"} based on size`)}if(S+="## Summary\n",S+=`- **Files Modified**: ${_.size}\n`,S+=`- **Total File Operations**: ${C.length}\n`,S+="- **What's Shown**: For existing files, comparing state before task started with final state.\n",S+=" For files created during task, showing the entire file as created.\n",P?(S+=`- **Diff Display**: Limited (total diff size of ${q} lines exceeds limit of ${T} lines)\n`,S+=" Use file-history tool with individual files to see detailed changes\n\n"):S+=`- **Diff Display**: ${m?"Enabled":"Disabled"} (use showDiff=${!m} to ${m?"hide":"show"} diffs)\n\n`,v.allMoves.length>0){S+="## Move Operations\n\n",S+=`Detected ${v.allMoves.length} file move operation(s):\n\n`
|
|
4006
4051
|
for(const je of v.allMoves)S+=`- **${je.source}** \u2192 **${je.destination}**\n`,S+=` - Operation: ${je.type}\n`,S+=` - Timestamp: ${new Date(je.timestamp).toLocaleString()}\n`,S+=` - Record ID: ${je.recordId}\n\n`}S+="## Modified Files\n\n"
|
|
4007
|
-
for(const[Re
|
|
4052
|
+
for(const[xe,Re]of E.entries()){const{normalizedPath:Me,fullPath:Oe}=d.validateAndNormalizePath(xe,t)
|
|
4008
4053
|
let $e=!1
|
|
4009
|
-
try{await a.access(Oe),$e=!0}catch{}S+=`### ${
|
|
4010
|
-
const De=new Date(
|
|
4011
|
-
S+=`**First Change**: ${De}\n`,S+=`**Last Change**: ${Ae}\n`,"pre-task"===
|
|
4012
|
-
const Fe=v.sourceToMove.get(
|
|
4013
|
-
Fe?S+=`**\u2139\ufe0f Move Operation**: This file was moved TO **${Fe.destination}**\n`:Ne&&(S+=`**\u2139\ufe0f Move Operation**: This file was moved FROM **${Ne.source}**\n`),m&&!P?
|
|
4054
|
+
try{await a.access(Oe),$e=!0}catch{}S+=`### ${xe} ${$e?"":"(Deleted)"}\n\n`
|
|
4055
|
+
const De=new Date(Re.firstChange.timestamp).toLocaleString(),Ae=new Date(Re.lastChange.timestamp).toLocaleString()
|
|
4056
|
+
S+=`**First Change**: ${De}\n`,S+=`**Last Change**: ${Ae}\n`,"pre-task"===Re.firstChange.status&&Re.firstChange.commitHash?S+=`**Pre-Task Commit**: ${Re.firstChange.commitHash.substring(0,8)}\n`:Re.firstChange.commitHash&&(S+=`**File Created During Task**: ${Re.firstChange.commitHash.substring(0,8)}\n`),Re.lastChange.commitHash&&(S+=`**Final Commit**: ${Re.lastChange.commitHash.substring(0,8)}\n`)
|
|
4057
|
+
const Fe=v.sourceToMove.get(xe),Ne=v.destToMove.get(xe)
|
|
4058
|
+
Fe?S+=`**\u2139\ufe0f Move Operation**: This file was moved TO **${Fe.destination}**\n`:Ne&&(S+=`**\u2139\ufe0f Move Operation**: This file was moved FROM **${Ne.source}**\n`),m&&!P?Re.hasDiff?(S+="\n**Changes**:\n",S+="```diff\n",S+=Re.diffText,S+="\n```\n\n"):S+=`\n**Note**: ${Re.diffText}\n\n`:P&&Re.hasDiff?(S+=`\n**Note**: File has changes (${Re.diffText?Re.diffText.split("\n").length:0} lines). `,S+=`Compare ${Re.firstChange.commitHash?Re.firstChange.commitHash.substring(0,8):"unknown"}..${Re.lastChange.commitHash?Re.lastChange.commitHash.substring(0,8):"unknown"} to see changes.\n\n`):Re.hasDiff?S+="\n**Note**: File has changes. Use showDiff=true to see the diff.\n\n":S+=`\n**Note**: ${Re.diffText}\n\n`,S+="---\n\n"}return p({success:!0,fileCount:_.size}),{content:[{type:"text",text:S}]}}catch(ze){return s.error("Error in task file history tool",{error:ze instanceof Error?ze.stack:ze+""}),p({success:!1,error:ze instanceof Error?ze.name:"unknown"}),{content:[{type:"text",text:"Error: "+(0,u.getErrorMessage)(ze)}],isError:!0}}}
|
|
4014
4059
|
const i=t(9860),a=s(t(1943)),c=t(9671),l=t(2960),d=s(t(5967)),u=t(8824),h=t(4466)},6928(module){"use strict"
|
|
4015
4060
|
module.exports=require("path")},6975(e,exports,t){"use strict"
|
|
4016
4061
|
Object.defineProperty(exports,"__esModule",{value:!0}),exports.ProjectClientAdapter=void 0
|
|
@@ -4171,8 +4216,9 @@ p.debug("Create request response structure",{type:typeof k,isArray:Array.isArray
|
|
|
4171
4216
|
const v=(0,o.extractDataFromResponse)(k,{logger:p,operationName:"createRequest",throwOnNoData:!0}),C="data"in v?v.data:v
|
|
4172
4217
|
let _,E={created:!1}
|
|
4173
4218
|
if(u?.workspaceManager)try{await u.workspaceManager.initializeRequest(C.id,C.title),E={created:!0,branchName:"requests/"+C.id,message:"Branch created successfully"},p.info("Request branch initialized successfully",{requestId:C.id,branchName:E.branchName,title:C.title})}catch(e){p.warn("Failed to initialize request branch, will retry on first operation",{requestId:C.id,error:(0,i.getErrorMessage)(e)})}else"quick-edit"===l.type?p.info("Quick-edit request - skipping branch creation, will work directly on main",{requestId:C.id}):p.debug("No workspace manager available, branch creation deferred",{requestId:C.id})
|
|
4174
|
-
p.info("Request created successfully",{requestId:C.id,title:C.title,branchCreated:E.created,branchName:E.branchName})
|
|
4175
|
-
|
|
4219
|
+
if(p.info("Request created successfully",{requestId:C.id,title:C.title,branchCreated:E.created,branchName:E.branchName}),l.questDocumentId)try{const e=c.getDocumentClient(),t=await e.getDocument(l.questDocumentId)
|
|
4220
|
+
if(t&&"Quest"===t.type){const r={...t.metadata||{},consecutiveDoneAudits:0}
|
|
4221
|
+
await e.updateDocument(l.questDocumentId,{metadata:r}),p.info("Reset quest consecutiveDoneAudits after spawning request",{questDocumentId:l.questDocumentId,requestId:C.id})}}catch(e){p.warn("Failed to reset quest consecutiveDoneAudits after request creation",{questDocumentId:l.questDocumentId,requestId:C.id,error:(0,i.getErrorMessage)(e)})}try{const e=c.getToolRecordClient()
|
|
4176
4222
|
if(e){const t=await e.createToolRecord({requestId:C.id,projectId:m,type:"create-request",metadata:{status:"completed",timestamp:(new Date).toISOString(),requestType:C.type,requestTitle:C.title,requestDescription:C.description,criteriaCount:C.acceptanceCriteria.length,branchCreated:E.created,branchName:E.created?E.branchName:null},note:`Created request "${C.title}" of type ${C.type}${E.created?" with branch "+E.branchName:" - branch will be created on first file operation"}`})
|
|
4177
4223
|
_=t?.id}}catch(e){p.warn("Failed to create tool record for request creation",{error:(0,i.getErrorMessage)(e),requestId:C.id})}g({success:!0,type:l.type,hasProjectId:!0}),p.info("Request created successfully",{requestId:C.id,title:C.title,type:C.type,projectId:m})
|
|
4178
4224
|
const S=C.localId||C.id
|
|
@@ -4369,23 +4415,27 @@ const h=t(3444),p=t(9860),g=t(3922),m=t(8824),f=u(t(9896)),y=u(t(6928))
|
|
|
4369
4415
|
t(857)},7575(e,exports){"use strict"
|
|
4370
4416
|
var t
|
|
4371
4417
|
Object.defineProperty(exports,"__esModule",{value:!0}),exports.FileOperationPhase=void 0,function(e){e.VALIDATION="validation",e.TASK_VALIDATION="task_validation",e.RECORD_CREATION="record_creation",e.FILE_WRITE="file_write",e.STRING_REPLACEMENT="string_replacement",e.GIT_COMMIT="git_commit",e.RECORD_UPDATE_SUCCESS="record_update_success",e.RECORD_UPDATE_FAILURE="record_update_failure"}(t||(exports.FileOperationPhase=t={}))},7609(e,exports,t){"use strict"
|
|
4372
|
-
Object.defineProperty(exports,"__esModule",{value:!0}),exports.handleUpdatePlan=async function(e,t,
|
|
4373
|
-
try{const t=
|
|
4418
|
+
Object.defineProperty(exports,"__esModule",{value:!0}),exports.handleUpdatePlan=async function(e,t,o,s){const i=s.child({tool:"plan_operations",operation:"update"})
|
|
4419
|
+
try{const t=o.getDocumentClient(),r=await t.getDocument(e.planId)
|
|
4374
4420
|
if(!r)return{content:[{type:"text",text:"\u274c Plan not found: "+e.planId}],isError:!0}
|
|
4375
|
-
const
|
|
4376
|
-
if("Plan"!==r.type&&!
|
|
4377
|
-
const
|
|
4378
|
-
void 0!==e.content&&(
|
|
4379
|
-
const
|
|
4380
|
-
if(
|
|
4421
|
+
const s="Quest"===r.type
|
|
4422
|
+
if("Plan"!==r.type&&!s)return{content:[{type:"text",text:`\u274c Document ${e.planId} is not a plan or quest (type: ${r.type})`}],isError:!0}
|
|
4423
|
+
const a={}
|
|
4424
|
+
void 0!==e.content&&(a.content=e.content),e.name&&(a.filename=e.name.replace(/\.md$/i,"")+".md")
|
|
4425
|
+
const c=e.metadata||{},l=n.QUEST_METADATA_KEYS.filter((e=>void 0!==c[e]))
|
|
4426
|
+
if(l.length>0){if(!s)return{content:[{type:"text",text:`\u274c Metadata fields (${l.join(", ")}) are only valid on Quest documents. ${e.planId} is a Plan.`}],isError:!0}
|
|
4427
|
+
if(void 0!==c.status&&!n.QUEST_STATUSES.includes(c.status))return{content:[{type:"text",text:`\u274c Invalid quest status "${c.status}". Allowed: ${n.QUEST_STATUSES.join(", ")}.`}],isError:!0}
|
|
4428
|
+
if(void 0!==c.completionMode&&!n.QUEST_COMPLETION_MODES.includes(c.completionMode))return{content:[{type:"text",text:`\u274c Invalid completionMode "${c.completionMode}". Allowed: ${n.QUEST_COMPLETION_MODES.join(", ")}.`}],isError:!0}
|
|
4381
4429
|
const t={...r.metadata||{}}
|
|
4382
|
-
for(const e of
|
|
4383
|
-
|
|
4384
|
-
const
|
|
4385
|
-
|
|
4386
|
-
const u=
|
|
4387
|
-
|
|
4388
|
-
const
|
|
4430
|
+
for(const e of l)t[e]=c[e]
|
|
4431
|
+
a.metadata=t}if(void 0===a.content&&!a.filename&&!a.metadata)return{content:[{type:"text",text:"\u274c No changes supplied. Provide content, name, or quest metadata."}],isError:!0}
|
|
4432
|
+
const d=r.metadata||{}
|
|
4433
|
+
if(d.isStub){const e=a.metadata??{...d}
|
|
4434
|
+
delete e.isStub,a.metadata=e}const u=await t.updateDocument(e.planId,a),h=u.localId||u.id
|
|
4435
|
+
i.info("Plan/Quest updated",{planId:h,isQuest:s,changedMetadata:l})
|
|
4436
|
+
const p=s?"Quest":"Plan",g=[]
|
|
4437
|
+
return void 0!==a.content&&g.push("content"),a.filename&&g.push("filename="+u.filename),l.length>0&&g.push(`metadata(${l.join(", ")})`),{content:[{type:"text",text:`\u2705 **${p} Updated**\n\n**ID:** ${h}\n**Filename:** ${u.filename}\n**Changes:** ${g.join(", ")}\n**Updated:** `+new Date(u.updatedAt).toLocaleString()}]}}catch(e){return i.error("Failed to update plan/quest",{error:(0,r.getErrorMessage)(e)}),{content:[{type:"text",text:"\u274c **Failed to update:** "+(0,r.getErrorMessage)(e)}],isError:!0}}}
|
|
4438
|
+
const r=t(8824),n=t(3416)},7613(e,exports,t){"use strict"
|
|
4389
4439
|
Object.defineProperty(exports,"__esModule",{value:!0}),exports.def=void 0
|
|
4390
4440
|
const r=t(6183),n=t(9072)
|
|
4391
4441
|
exports.def={name:"session_message_operations",description:'Inter-session messaging (questions and reports).\n\nOperations:\n\u2022 send - Send a message (type: "question" or "report")\n\u2022 reply - Reply to a message (answer a question or acknowledge a report). Type inferred from code prefix (Q-/R-).\n\u2022 list - List messages (filter by messageType, direction, status)\n\u2022 get - Get a message by its code\n\u2022 offer-handoff - Present the user with a choice to start building or keep planning\n\nMessage codes: Q-{id}-{seq} for questions, R-{id}-{seq} for reports.',schema:r.SessionMessageOperationsSchema,annotations:{title:"Session Message Operations",readOnlyHint:!1,destructiveHint:!1,idempotentHint:!1},handler(e,t){return(0,n.handleSessionMessageOperations)(e,t.context,t.logger,t.metrics,t.apiClient??void 0,t.cliOrigin)}}},7617(e,exports,t){"use strict"
|
|
@@ -4800,19 +4850,19 @@ const S=await l.validateTaskId(C,_,n,m,p,I.metricsPrefix),T=S?.requestId,q=await
|
|
|
4800
4850
|
P.taskPromoted&&m.info(`Auto-promoted task ${C} (${S.title||"Untitled"}) to in_progress for file operation`,{taskId:C,taskTitle:S.title,previousStatus:S.status,newStatus:P.newTaskStatus,path:_}),P.requestPromoted&&m.info(`Auto-promoted request ${T} to in_progress for file operation`,{requestId:T,previousStatus:q.request?.status,newStatus:P.newRequestStatus,triggeringTaskId:C})
|
|
4801
4851
|
const j=await l.ensureCorrectWorkspaceContext({taskPromoted:P.taskPromoted,requestId:T,context:r,operation:"create-directory",logger:m,metrics:p,metricsPrefix:I.metricsPrefix})
|
|
4802
4852
|
if(!j.success)throw Error(j.error)
|
|
4803
|
-
let
|
|
4804
|
-
try{
|
|
4805
|
-
const{toolRecordId:
|
|
4806
|
-
y=
|
|
4807
|
-
let O=
|
|
4808
|
-
if(!
|
|
4853
|
+
let x=!1
|
|
4854
|
+
try{x=(await a.default.stat(E)).isDirectory()}catch{x=!1}b=l.FileOperationPhase.RECORD_CREATION,p.incrementCounter("create_directory_phase",1,{phase:b})
|
|
4855
|
+
const{toolRecordId:R,localToolRecordId:M}=await l.createFileOperationRecords(C,T,r.projectId,I.recordType,_,{directoryExists:x,userComment:h},n,o,m,p,I.metricsPrefix,g)
|
|
4856
|
+
y=R,w=R,b=I.fileOperationPhase,p.incrementCounter("create_directory_phase",1,{phase:b})
|
|
4857
|
+
let O=x
|
|
4858
|
+
if(!x){await a.default.mkdir(E,{recursive:!0}),m.info("Successfully created directory "+_)
|
|
4809
4859
|
try{const e=c.default.join(E,".gitkeep")
|
|
4810
4860
|
await a.default.writeFile(e,"# This file makes the directory trackable by Git\n"),O=!0,m.info("Created .gitkeep file for Git tracking")}catch(e){m.warn("Failed to create .gitkeep file",{error:e instanceof Error?e.message:e+""}),O=!1}}const $=Date.now()-f
|
|
4811
4861
|
p.recordValue("create_directory_time",$),p.incrementCounter("create_directory_success",1),b=l.FileOperationPhase.GIT_COMMIT,p.incrementCounter("create_directory_phase",1,{phase:b})
|
|
4812
|
-
const D=`Create directory: ${_} - ${h||"Create directory"}`,A=!
|
|
4813
|
-
b=l.FileOperationPhase.RECORD_UPDATE_SUCCESS,p.incrementCounter("create_directory_phase",1,{phase:b}),await l.updateFileOperationRecords(C,y,w,_,I.recordType,`Successfully ${
|
|
4862
|
+
const D=`Create directory: ${_} - ${h||"Create directory"}`,A=!x&&O?_+"/.gitkeep":_,F=await l.commitToGit(C,A,R,M,D,r,m,p,I.metricsPrefix)
|
|
4863
|
+
b=l.FileOperationPhase.RECORD_UPDATE_SUCCESS,p.incrementCounter("create_directory_phase",1,{phase:b}),await l.updateFileOperationRecords(C,y,w,_,I.recordType,`Successfully ${x?"verified":"created"} directory: ${_}`,{status:"completed",commitHash:F.commitHash,previousCommitHash:F.previousCommitHash,directoryExists:x,isDirectory:!0,userComment:h},`Successfully ${x?"verified":"created"} directory: ${_}`,n,o,m,p,I.metricsPrefix)
|
|
4814
4864
|
const N=r.getCurrentBranchContext?await r.getCurrentBranchContext():{branch:null,requestId:null,isMain:!0}
|
|
4815
|
-
return{content:[{type:"text",text:
|
|
4865
|
+
return{content:[{type:"text",text:x?"Directory already exists":`Successfully created directory${F.commitHash?"\nCommit: "+F.commitHash.substring(0,8):""}${N.requestId&&!N.permanentBranch?"\nBranch: "+N.requestId:""}`}]}}catch(t){if(e.taskId&&o)try{const n=t instanceof d.NotFoundError||t instanceof d.ValidationError||t instanceof u.ZodError
|
|
4816
4866
|
await o.createToolRecord({...n?{}:{taskId:e.taskId},projectId:r.projectId,type:"create-directory",metadata:{status:"failed",timestamp:(new Date).toISOString(),path:e.path,userComment:e.comment,error:(0,h.getErrorMessage)(t),errorDetails:t instanceof Error?t.stack:t+"",phase:b,attemptedTaskId:e.taskId,taskIdValidationFailed:n},note:`Failed to create directory ${e.path} - ${(0,h.getErrorMessage)(t)}`})}catch(t){m.error("Failed to create failure record for create directory operation",{error:t instanceof Error?t.message:t+"",taskId:e.taskId,path:e.path})}const s=Date.now()-f
|
|
4817
4867
|
if(p.recordValue("create_directory_time",s),p.incrementCounter("create_directory_errors",1),m.error("Error creating directory:",{error:(0,h.getErrorMessage)(t),time:s}),(y||w)&&e.taskId){b=l.FileOperationPhase.RECORD_UPDATE_FAILURE
|
|
4818
4868
|
try{await l.updateFileOperationRecords(e.taskId,y,w,e.path,I.recordType,"Failed to create directory "+e.path,{status:"failed",error:(0,h.getErrorMessage)(t),userComment:e.comment},"Failed to create directory "+e.path,n,o,m,p,I.metricsPrefix)}catch(t){m.error("Failed to update record with failure status",{taskId:e.taskId,recordId:y,error:t instanceof Error?t.message:t+""})}}return l.handleFileOperationError(t,b,m,p,e,I)}}
|
|
@@ -5425,10 +5475,10 @@ Object.defineProperty(exports,"__esModule",{value:!0}),exports.handleReplaceInFi
|
|
|
5425
5475
|
let C,_=u.FileOperationPhase.VALIDATION
|
|
5426
5476
|
try{const E=e,{enforceActiveTask:S}=await Promise.resolve().then(t.bind(t,3451)),T=await S(r,o,a,e.taskId)
|
|
5427
5477
|
if("errorResult"in T)return T.errorResult
|
|
5428
|
-
const{taskId:q}=T,{operations:P,fuzzy_match:j=!0,comment:
|
|
5429
|
-
k.info("Replace in files batch operation",{taskId:q,operationCount:P.length,totalReplacements:P.reduce(((e,t)=>e+t.replacements.length),0),globalFuzzyMatch:j,comment:
|
|
5430
|
-
const
|
|
5431
|
-
if(
|
|
5478
|
+
const{taskId:q}=T,{operations:P,fuzzy_match:j=!0,comment:x}=E
|
|
5479
|
+
k.info("Replace in files batch operation",{taskId:q,operationCount:P.length,totalReplacements:P.reduce(((e,t)=>e+t.replacements.length),0),globalFuzzyMatch:j,comment:x})
|
|
5480
|
+
const R=P.filter((e=>e.documentId)).map((e=>e.documentId))
|
|
5481
|
+
if(R.length>0&&r.apiClient)try{await(0,f.ensureDocumentsNotLocked)(R,r.apiClient,k,c,"replace_in_files-documents")}catch(e){if(e instanceof p.ValidationError)return{content:[{type:"text",text:e.message}],isError:!0}
|
|
5432
5482
|
throw e}_=u.FileOperationPhase.TASK_VALIDATION,c.incrementCounter("replace_in_files_phase",1,{phase:_})
|
|
5433
5483
|
const M=P[0],O=M.documentId?"document:"+M.documentId:M.path
|
|
5434
5484
|
let $=Date.now()
|
|
@@ -5443,7 +5493,7 @@ const t=await u.autoPromoteTaskStatus(q,D.status,A,e.request?.status,O,o,i,k,c,"
|
|
|
5443
5493
|
t.taskPromoted&&k.info("Auto-promoted task to in_progress",{taskId:q,requestId:A,previousStatus:D.status,newStatus:t.newTaskStatus}),Date.now(),$=Date.now()
|
|
5444
5494
|
const n=await u.ensureCorrectWorkspaceContext({taskPromoted:t.taskPromoted,requestId:A,context:r,operation:"replace_in_files",logger:k,metrics:c,metricsPrefix:"replace_in_files"})
|
|
5445
5495
|
if(!n.success)throw Error(n.error)
|
|
5446
|
-
Date.now(),N=!0}if(
|
|
5496
|
+
Date.now(),N=!0}if(R.length>0&&A)try{await(0,g.validateRequestStatusForDocumentOperation)(A,i,k,c,"replace_in_files-documents")}catch(e){if(e instanceof p.ValidationError)return{content:[{type:"text",text:e.message}],isError:!0}
|
|
5447
5497
|
throw e}$=Date.now()
|
|
5448
5498
|
const z=new Map
|
|
5449
5499
|
if(k.info("\u{1f50d} Starting external edit detection",{hasFileOperations:F,hasGit:!!r.git,operationCount:P.length}),F&&r.git)for(const e of P)if(e.path&&!e.documentId)try{const t=u.validateAndNormalizePath(e.path,r),n=await l.default.readFile(t.fullPath,"utf8"),o=void 0!==e.fuzzy_match?e.fuzzy_match:j,s=[]
|
|
@@ -5454,15 +5504,15 @@ const i=await(0,w.detectExternalEdits)(r.git,o,k)
|
|
|
5454
5504
|
k.info("\u{1f50d} External edit detection result",{path:t.normalizedPath,hasExternalEdits:i.hasExternalEdits,conflictingLines:i.conflictingLines,hasMessage:!!i.message}),i.hasExternalEdits&&i.message?(z.set(e.path,{message:i.message,debugInfo:i.debugInfo}),k.warn("\u26a0\ufe0f External edits detected before auto-commit",{path:t.normalizedPath,conflictingLines:i.conflictingLines})):(i.debugInfo&&z.set(e.path,{message:"",debugInfo:i.debugInfo}),k.info("\u2705 No external edit conflicts detected",{path:t.normalizedPath}))}else k.info("\u2139\ufe0f No matches found for external edit detection",{path:t.normalizedPath}),z.set(e.path,{message:"",debugInfo:{detectionRan:!1,reason:"No matches found - patterns not found in file",affectedRegion:"none",uncommittedChanges:"not checked",overlapDetected:!1}})}catch(t){k.warn("Failed to check for external edits before auto-commit",{path:e.path,error:(0,b.getErrorMessage)(t)})}if(Date.now(),$=Date.now(),F&&r.git)try{k.debug("[REPLACE-IN-FILES] Checking for user changes before batch operation")
|
|
5455
5505
|
const e=await(0,m.commitUserChangesBeforeToolOperation)(r.git,"replace_in_files",{requestId:A,taskId:q,workspaceManager:r.workspaceManager},k,c)
|
|
5456
5506
|
e.userChangesCommitted&&(k.debug("[REPLACE-IN-FILES] User changes committed",{commitHash:e.commitHash?.substring(0,8),filesCommitted:e.filesCommitted}),k.info("User changes committed before batch operation",{taskId:q,userCommitHash:e.commitHash?.substring(0,8),userFilesCommitted:e.filesCommitted}))}catch(e){k.warn("Pre-tool user changes commit failed",{taskId:q,error:e instanceof Error?e.message:e+""})}Date.now(),$=Date.now(),_=u.FileOperationPhase.RECORD_CREATION,c.incrementCounter("replace_in_files_phase",1,{phase:_})
|
|
5457
|
-
const{toolRecordId:L}=await u.createFileOperationRecords(q,A,r.projectId,"replace-in-files",O,{operationCount:P.length,totalReplacements:P.reduce(((e,t)=>e+t.replacements.length),0),globalFuzzyMatch:j,userComment:
|
|
5507
|
+
const{toolRecordId:L}=await u.createFileOperationRecords(q,A,r.projectId,"replace-in-files",O,{operationCount:P.length,totalReplacements:P.reduce(((e,t)=>e+t.replacements.length),0),globalFuzzyMatch:j,userComment:x},o,s,k,c,"replace_in_files",I)
|
|
5458
5508
|
C=L,Date.now(),$=Date.now(),_=u.FileOperationPhase.STRING_REPLACEMENT,c.incrementCounter("replace_in_files_phase",1,{phase:_})
|
|
5459
5509
|
const H=[],B=[]
|
|
5460
5510
|
for(const e of P){const t=e.path?z.get(e.path):void 0,o=await n(e,j,r,0,0,t?.message,t?.debugInfo)
|
|
5461
5511
|
H.push(o),o.successfulReplacements>0&&"file"===o.type&&o.path&&B.push(o.path)}Date.now(),$=Date.now()
|
|
5462
5512
|
const U=P.filter((e=>e.path&&!e.documentId)).map((e=>({path:e.path}))),G=await u.handleMultiFileGitCommit(q,U,H,B.length,{operationType:"Replace in files",toolRecordId:L||C||"unknown",successField:"successfulReplacements",logger:k,metrics:c,metricsPrefix:"replace_in_files"},r),W=G.commitHash
|
|
5463
5513
|
Date.now(),Date.now()
|
|
5464
|
-
const V=H.filter((e=>e.success)).length,
|
|
5465
|
-
await s.updateToolRecord(C,{metadata:{path:O,status:0===
|
|
5514
|
+
const V=H.filter((e=>e.success)).length,Q=H.length-V,K=H.reduce(((e,t)=>e+t.successfulReplacements),0),J=H.reduce(((e,t)=>e+t.failedReplacements),0),Y=H.map((e=>({type:e.type,path:e.path,documentId:e.documentId,filename:e.filename,replacements:e.replacements.map((e=>({old_str:e.old,new_str:e.new,success:e.success,error:e.error,matchesFound:e.matchesFound,matchType:e.matchType,lines:e.lines})))}))),Z=H.filter((e=>e.success)).map((e=>({path:e.path,documentId:e.documentId,filename:e.filename,successfulReplacements:e.successfulReplacements,failedReplacements:e.failedReplacements}))),X=H.filter((e=>!e.success)).map((e=>({path:e.path,documentId:e.documentId,filename:e.filename,error:e.error,successfulReplacements:e.successfulReplacements,failedReplacements:e.failedReplacements})))
|
|
5515
|
+
await s.updateToolRecord(C,{metadata:{path:O,status:0===Q?"completed":"partial",operationCount:P.length,operations:Y,successfulFiles:Z,failedFiles:X,successfulReplacements:K,failedReplacements:J,processingTime:Date.now()-v,userComment:x,...G.success&&G.commitHash&&{commitHash:G.commitHash,previousCommitHash:G.previousCommitHash||void 0}}})
|
|
5466
5516
|
const ee=await async function(e,t,r,n,o){const s=e.filter((e=>e.success)).length,i=e.length-s,a=e.filter((e=>!e.success&&!e.error&&e.successfulReplacements>0)).length
|
|
5467
5517
|
let c="## Replace In Files - Batch Results\n\n"
|
|
5468
5518
|
if(o.workspaceManager)try{const e=o.workspaceManager.getCurrentContext(o.currentSessionId)
|
|
@@ -5476,8 +5526,8 @@ if(s.length>0){c+="\n**Failed Replacement Details:**\n"
|
|
|
5476
5526
|
for(const e of s)c+=`- \u274c \`${e.old.substring(0,40)}${e.old.length>40?"...":""}\` \u2192 \`${e.new.substring(0,40)}${e.new.length>40?"...":""}\`: ${e.error}\n`,e.details&&e.details.length>0&&(c+=" **Candidates found:**\n",c+=e.details.slice(0,5).map((e=>` - Line ${e.line}: \`${e.actually_matched.substring(0,40)}${e.actually_matched.length>40?"...":""}\` (${e.match_type})`)).join("\n")+"\n",e.details.length>5&&(c+=` ... and ${e.details.length-5} more matches\n`)),e.similarMatches&&e.similarMatches.length>0&&(c+=" **Did you mean? (Similar matches found):**\n",c+=e.similarMatches.map((e=>` - Line ${e.line}: \`${e.text.substring(0,60)}${e.text.length>60?"...":""}\` (${e.reason}, similarity: ${(100*e.similarity).toFixed(0)}%)`)).join("\n")+"\n")}c+="\n"}const l=e.filter((e=>"document"===e.type&&(e.success||e.successfulReplacements>0)))
|
|
5477
5527
|
l.length>0&&(c+=`\n**Document Changes:** ${l.length} modified document(s) synced back to tracking system.\n`)
|
|
5478
5528
|
const d=o.workspaceManager?.consumeLargeFileWarning(o.currentSessionId)
|
|
5479
|
-
return d&&(c+=d),c}(H,W,J,
|
|
5480
|
-
return{content:[{type:"text",text:ee}],isError:0===
|
|
5529
|
+
return d&&(c+=d),c}(H,W,K,J,r)
|
|
5530
|
+
return{content:[{type:"text",text:ee}],isError:0===K,...(0,d.alchemyMeta)({kind:"replace-in-files",toolRecordId:C,failed:J>0})}}catch(e){const t=Date.now()-v
|
|
5481
5531
|
if(k.error("Replace in files batch operation failed",{error:e instanceof Error?e.stack:e+"",duration:t,phase:_}),C)try{await s.updateToolRecord(C,{metadata:{status:"failed",error:(0,b.getErrorMessage)(e),phase:_,duration:t}})}catch(e){}return c.incrementCounter("replace_in_files_errors",1,{phase:_}),{content:[{type:"text",text:"\u274c **Replace In Files Failed:** "+(0,b.getErrorMessage)(e)}],isError:!0}}},c(t(857))
|
|
5482
5532
|
const l=c(t(1943)),d=(a(t(9896)),a(t(6928)),c(t(6982)),t(2272)),u=a(t(5967)),h=t(3626),p=t(9860),g=t(5003),m=t(7478),f=t(9949),y=t(9947),w=t(1318),b=t(8824)},9470(e,exports){"use strict"
|
|
5483
5533
|
Object.defineProperty(exports,"__esModule",{value:!0}),exports.parseLineSpec=function(e){if(!e||""===e.trim())throw Error("Line specification cannot be empty")
|