agent-device 0.6.2 → 0.7.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +79 -8
- package/dist/src/735.js +3 -0
- package/dist/src/bin.js +50 -41
- package/dist/src/daemon.js +29 -23
- package/ios-runner/AgentDeviceRunner/AgentDeviceRunner.xcodeproj/project.pbxproj +14 -6
- package/ios-runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests.swift +104 -4
- package/package.json +4 -2
- package/skills/agent-device/SKILL.md +29 -2
- package/skills/agent-device/references/logs-and-debug.md +5 -0
- package/skills/agent-device/references/perf-metrics.md +53 -0
- package/skills/dogfood/SKILL.md +183 -0
- package/skills/dogfood/references/issue-taxonomy.md +83 -0
- package/skills/dogfood/templates/dogfood-report-template.md +52 -0
- package/dist/src/350.js +0 -3
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
# Issue Taxonomy (Mobile)
|
|
2
|
+
|
|
3
|
+
Reference for categorizing issues found during mobile dogfooding.
|
|
4
|
+
|
|
5
|
+
## Severity Levels
|
|
6
|
+
|
|
7
|
+
| Severity | Definition |
|
|
8
|
+
|----------|------------|
|
|
9
|
+
| **critical** | Blocks a core workflow, causes data loss, or crashes/freeze loops the app |
|
|
10
|
+
| **high** | Major feature broken or unusable, no practical workaround |
|
|
11
|
+
| **medium** | Feature works with notable friction or partial failure; workaround exists |
|
|
12
|
+
| **low** | Minor cosmetic or polish issue |
|
|
13
|
+
|
|
14
|
+
## Categories
|
|
15
|
+
|
|
16
|
+
### Visual / UI
|
|
17
|
+
|
|
18
|
+
- Layout broken, clipped, overlapped, or unreadable text
|
|
19
|
+
- Safe-area/notch overlap issues
|
|
20
|
+
- Incorrect dark/light appearance rendering
|
|
21
|
+
- Missing assets/icons
|
|
22
|
+
- Animation glitches or flicker
|
|
23
|
+
|
|
24
|
+
### Functional
|
|
25
|
+
|
|
26
|
+
- Buttons/controls do nothing or trigger wrong action
|
|
27
|
+
- Flows fail (create/edit/delete/submit)
|
|
28
|
+
- Navigation dead-ends or wrong destination
|
|
29
|
+
- State loss after background/foreground transitions
|
|
30
|
+
- Deep link opens wrong screen or fails
|
|
31
|
+
|
|
32
|
+
### UX
|
|
33
|
+
|
|
34
|
+
- Confusing hierarchy or navigation labels
|
|
35
|
+
- Missing loading/progress feedback
|
|
36
|
+
- Unclear error handling or no recovery affordance
|
|
37
|
+
- Excessive steps for common tasks
|
|
38
|
+
- Inconsistent behavior between similar screens
|
|
39
|
+
|
|
40
|
+
### Content
|
|
41
|
+
|
|
42
|
+
- Typos, incorrect copy, placeholder text
|
|
43
|
+
- Wrong labels/help text
|
|
44
|
+
- Truncated text with no affordance
|
|
45
|
+
- Inconsistent terminology across screens
|
|
46
|
+
|
|
47
|
+
### Performance
|
|
48
|
+
|
|
49
|
+
- Slow startup or route transitions
|
|
50
|
+
- Input lag or gesture jank
|
|
51
|
+
- Scroll hitches/frame drops
|
|
52
|
+
- Notable battery/thermal symptoms during basic usage
|
|
53
|
+
|
|
54
|
+
### Diagnostics / Logs
|
|
55
|
+
|
|
56
|
+
- Native crashes or repeated fatal exceptions
|
|
57
|
+
- Repeated warnings correlated with broken behavior
|
|
58
|
+
- Unhandled runtime errors visible during repro
|
|
59
|
+
|
|
60
|
+
### Permissions / Platform
|
|
61
|
+
|
|
62
|
+
- Permission prompt flow broken or loops forever
|
|
63
|
+
- Denied permissions not handled gracefully
|
|
64
|
+
- Platform-specific regressions (iOS-only or Android-only)
|
|
65
|
+
- Background/foreground lifecycle regressions
|
|
66
|
+
|
|
67
|
+
### Accessibility
|
|
68
|
+
|
|
69
|
+
- Missing labels or incorrect accessibility names
|
|
70
|
+
- Focus order/navigation issues for assistive tech
|
|
71
|
+
- Low contrast or unreadable text scaling
|
|
72
|
+
- Touch targets too small for reliable interaction
|
|
73
|
+
|
|
74
|
+
## Exploration Checklist
|
|
75
|
+
|
|
76
|
+
1. Visual scan: capture screenshot; verify layout/safe areas/text/icon rendering.
|
|
77
|
+
2. Interactions: press controls, open menus/modals, validate expected response.
|
|
78
|
+
3. Forms/input: test valid/invalid/empty/boundary input.
|
|
79
|
+
4. Navigation: traverse all top-level sections and return paths.
|
|
80
|
+
5. App states: loading/empty/error/offline/permission-denied/background-resume.
|
|
81
|
+
6. Logs/diagnostics: inspect app logs when behavior is suspicious.
|
|
82
|
+
7. Platform parity: verify critical flows on each requested platform.
|
|
83
|
+
8. Accessibility basics: labels, touch target sizes, readability/contrast.
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
# Dogfood Report: {APP_NAME}
|
|
2
|
+
|
|
3
|
+
| Field | Value |
|
|
4
|
+
|-------|-------|
|
|
5
|
+
| **Date** | {DATE} |
|
|
6
|
+
| **Platform** | {PLATFORM} |
|
|
7
|
+
| **Target App** | {TARGET_APP} |
|
|
8
|
+
| **Session** | {SESSION_NAME} |
|
|
9
|
+
| **Scope** | {SCOPE} |
|
|
10
|
+
|
|
11
|
+
## Summary
|
|
12
|
+
|
|
13
|
+
| Severity | Count |
|
|
14
|
+
|----------|-------|
|
|
15
|
+
| Critical | 0 |
|
|
16
|
+
| High | 0 |
|
|
17
|
+
| Medium | 0 |
|
|
18
|
+
| Low | 0 |
|
|
19
|
+
| **Total** | **0** |
|
|
20
|
+
|
|
21
|
+
## Issues
|
|
22
|
+
|
|
23
|
+
<!-- Copy this block for each issue found. Interactive issues need video + step screenshots. Static issues can be screenshot-only (Repro Video = N/A). -->
|
|
24
|
+
|
|
25
|
+
### ISSUE-001: {Short title}
|
|
26
|
+
|
|
27
|
+
| Field | Value |
|
|
28
|
+
|-------|-------|
|
|
29
|
+
| **Severity** | critical / high / medium / low |
|
|
30
|
+
| **Category** | visual / functional / ux / content / performance / diagnostics / permissions / accessibility |
|
|
31
|
+
| **Screen / Route** | {screen where issue was found} |
|
|
32
|
+
| **Repro Video** | {path to video, or N/A for static issues} |
|
|
33
|
+
|
|
34
|
+
**Description**
|
|
35
|
+
|
|
36
|
+
{What is wrong, what was expected, and what actually happened.}
|
|
37
|
+
|
|
38
|
+
**Repro Steps**
|
|
39
|
+
|
|
40
|
+
1. Open {screen/entry point}
|
|
41
|
+

|
|
42
|
+
|
|
43
|
+
2. {Action}
|
|
44
|
+

|
|
45
|
+
|
|
46
|
+
3. {Action}
|
|
47
|
+

|
|
48
|
+
|
|
49
|
+
4. **Observe:** {broken behavior}
|
|
50
|
+

|
|
51
|
+
|
|
52
|
+
---
|
package/dist/src/350.js
DELETED
|
@@ -1,3 +0,0 @@
|
|
|
1
|
-
import{AsyncLocalStorage as e}from"node:async_hooks";import t from"node:crypto";import r,{promises as n}from"node:fs";import o from"node:os";import i from"node:path";import{fileURLToPath as a,pathToFileURL as s}from"node:url";import{spawn as c,spawnSync as l}from"node:child_process";let d=new e,u=/(token|secret|password|authorization|cookie|api[_-]?key|access[_-]?key|private[_-]?key)/i,f=/(bearer\s+[a-z0-9._-]+|(?:api[_-]?key|token|secret|password)\s*[=:]\s*\S+)/i;function p(){return t.randomBytes(8).toString("hex")}async function m(e,r){let n={...e,diagnosticId:`${Date.now().toString(36)}-${t.randomBytes(4).toString("hex")}`,events:[]};return await d.run(n,r)}function h(){let e=d.getStore();return e?{diagnosticId:e.diagnosticId,requestId:e.requestId,session:e.session,command:e.command,debug:e.debug}:{}}function w(e){let t=d.getStore();if(!t)return;let n={ts:new Date().toISOString(),level:e.level??"info",phase:e.phase,session:t.session,requestId:t.requestId,command:t.command,durationMs:e.durationMs,data:e.data?S(e.data):void 0};if(t.events.push(n),!t.debug)return;let o=`[agent-device][diag] ${JSON.stringify(n)}
|
|
2
|
-
`;try{t.logPath&&r.appendFile(t.logPath,o,()=>{}),t.traceLogPath&&r.appendFile(t.traceLogPath,o,()=>{}),t.logPath||t.traceLogPath||process.stderr.write(o)}catch{}}async function g(e,t,r){let n=Date.now();try{let o=await t();return w({level:"info",phase:e,durationMs:Date.now()-n,data:r}),o}catch(t){throw w({level:"error",phase:e,durationMs:Date.now()-n,data:{...r??{},error:t instanceof Error?t.message:String(t)}}),t}}function y(e={}){let t=d.getStore();if(!t||!e.force&&!t.debug||0===t.events.length)return null;try{let e=(t.session??"default").replace(/[^a-zA-Z0-9._-]/g,"_"),n=new Date().toISOString().slice(0,10),a=i.join(o.homedir(),".agent-device","logs",e,n);r.mkdirSync(a,{recursive:!0});let s=new Date().toISOString().replace(/[:.]/g,"-"),c=i.join(a,`${s}-${t.diagnosticId}.ndjson`),l=t.events.map(e=>JSON.stringify(S(e)));return r.writeFileSync(c,`${l.join("\n")}
|
|
3
|
-
`),t.events=[],c}catch{return null}}function S(e){return function e(t,r,n){if(null==t)return t;if("string"==typeof t){var o=t,i=n;let e=o.trim();if(!e)return o;if(i&&u.test(i)||f.test(e))return"[REDACTED]";let r=function(e){try{let t=new URL(e);return t.search&&(t.search="?REDACTED"),(t.username||t.password)&&(t.username="REDACTED",t.password="REDACTED"),t.toString()}catch{return null}}(e);return r||(e.length>400?`${e.slice(0,200)}...<truncated>`:e)}if("object"!=typeof t)return t;if(r.has(t))return"[Circular]";if(r.add(t),Array.isArray(t))return t.map(t=>e(t,r));let a={};for(let[n,o]of Object.entries(t)){if(u.test(n)){a[n]="[REDACTED]";continue}a[n]=e(o,r,n)}return a}(e,new WeakSet)}class A extends Error{code;details;cause;constructor(e,t,r,n){super(t),this.code=e,this.details=r,this.cause=n}}function v(e){return e instanceof A?e:e instanceof Error?new A("UNKNOWN",e.message,void 0,e):new A("UNKNOWN","Unknown error",{err:e})}function I(e,t={}){let r=v(e),n=r.details?S(r.details):void 0,o=n&&"string"==typeof n.hint?n.hint:void 0,i=(n&&"string"==typeof n.diagnosticId?n.diagnosticId:void 0)??t.diagnosticId,a=(n&&"string"==typeof n.logPath?n.logPath:void 0)??t.logPath,s=o??function(e){switch(e){case"INVALID_ARGS":return"Check command arguments and run --help for usage examples.";case"SESSION_NOT_FOUND":return"Run open first or pass an explicit device selector.";case"TOOL_MISSING":return"Install required platform tooling and ensure it is available in PATH.";case"DEVICE_NOT_FOUND":return"Verify the target device is booted/connected and selectors match.";case"UNSUPPORTED_OPERATION":return"This command is not available for the selected platform/device.";case"COMMAND_FAILED":default:return"Retry with --debug and inspect diagnostics log for details.";case"UNAUTHORIZED":return"Refresh daemon metadata and retry the command."}}(r.code),c=function(e){if(!e)return;let t={...e};return delete t.hint,delete t.diagnosticId,delete t.logPath,Object.keys(t).length>0?t:void 0}(n),l=function(e,t,r){if("COMMAND_FAILED"!==e||r?.processExitError!==!0)return t;let n=function(e){let t=[/^an error was encountered processing the command/i,/^underlying error\b/i,/^simulator device failed to complete the requested operation/i];for(let r of e.split("\n")){let e=r.trim();if(e&&!t.some(t=>t.test(e)))return e.length>200?`${e.slice(0,200)}...`:e}return null}("string"==typeof r?.stderr?r.stderr:"");return n||t}(r.code,r.message,n);return{code:r.code,message:l,hint:s,diagnosticId:i,logPath:a,details:c}}function E(e){let t=[],r=[];for(let n of e){let e=n.depth??0;for(;t.length>0&&e<=t[t.length-1];)t.pop();let o=n.label?.trim()||n.value?.trim()||n.identifier?.trim()||"",i=N(n.type??"Element"),a="group"===i&&!o;a&&t.push(e);let s=a?e:Math.max(0,e-t.length);r.push({node:n,depth:s,type:i,text:D(n,s,a,i)})}return r}function D(e,t,r,n){let o=n??N(e.type??"Element"),i=b(e,o),a=" ".repeat(t),s=e.ref?`@${e.ref}`:"",c=[!1===e.enabled?"disabled":null].filter(Boolean).join(", "),l=c?` [${c}]`:"",d=i?` "${i}"`:"";return r?`${a}${s} [${o}]${l}`.trimEnd():`${a}${s} [${o}]${d}${l}`.trimEnd()}function b(e,t){var r,n;let o=e.label?.trim(),i=e.value?.trim();if("text-field"===(r=t)||"text-view"===r||"search"===r){if(i)return i;if(o)return o}else if(o)return o;if(i)return i;let a=e.identifier?.trim();return!a||(n=a,/^[\w.]+:id\/[\w.-]+$/i.test(n)&&("group"===t||"image"===t||"list"===t||"collection"===t))?"":a}function N(e){let t=e.replace(/XCUIElementType/gi,"").toLowerCase(),r=e.includes(".")&&(e.startsWith("android.")||e.startsWith("androidx.")||e.startsWith("com."));switch(t.includes(".")&&(t=t.replace(/^android\.widget\./,"").replace(/^android\.view\./,"").replace(/^android\.webkit\./,"").replace(/^androidx\./,"").replace(/^com\.google\.android\./,"").replace(/^com\.android\./,"")),t){case"application":return"application";case"navigationbar":return"navigation-bar";case"tabbar":return"tab-bar";case"button":case"imagebutton":return"button";case"link":return"link";case"cell":return"cell";case"statictext":case"checkedtextview":return"text";case"textfield":case"edittext":return"text-field";case"textview":return r?"text":"text-view";case"textarea":return"text-view";case"switch":return"switch";case"slider":return"slider";case"image":case"imageview":return"image";case"webview":return"webview";case"framelayout":case"linearlayout":case"relativelayout":case"constraintlayout":case"viewgroup":case"view":case"group":return"group";case"listview":case"recyclerview":return"list";case"collectionview":return"collection";case"searchfield":return"search";case"segmentedcontrol":return"segmented-control";case"window":return"window";case"checkbox":return"checkbox";case"radio":return"radio";case"menuitem":return"menu-item";case"toolbar":return"toolbar";case"scrollarea":case"scrollview":case"nestedscrollview":return"scroll-area";case"table":return"table";default:return t||"element"}}function $(){try{let e=M();return JSON.parse(r.readFileSync(i.join(e,"package.json"),"utf8")).version??"0.0.0"}catch{return"0.0.0"}}function M(){let e=i.dirname(a(import.meta.url)),t=e;for(let e=0;e<6;e+=1){let e=i.join(t,"package.json");if(r.existsSync(e))return t;t=i.dirname(t)}return e}async function _(e,t,r={}){return new Promise((n,o)=>{let i=c(e,t,{cwd:r.cwd,env:r.env,stdio:["pipe","pipe","pipe"],detached:r.detached}),a="",s=r.binaryStdout?Buffer.alloc(0):void 0,l="",d=!1,u=F(r.timeoutMs),f=u?setTimeout(()=>{d=!0,i.kill("SIGKILL")},u):null;r.binaryStdout||i.stdout.setEncoding("utf8"),i.stderr.setEncoding("utf8"),void 0!==r.stdin&&i.stdin.write(r.stdin),i.stdin.end(),i.stdout.on("data",e=>{r.binaryStdout?s=Buffer.concat([s??Buffer.alloc(0),Buffer.isBuffer(e)?e:Buffer.from(e)]):a+=e}),i.stderr.on("data",e=>{l+=e}),i.on("error",r=>{(f&&clearTimeout(f),"ENOENT"===r.code)?o(new A("TOOL_MISSING",`${e} not found in PATH`,{cmd:e},r)):o(new A("COMMAND_FAILED",`Failed to run ${e}`,{cmd:e,args:t},r))}),i.on("close",i=>{f&&clearTimeout(f);let c=i??1;d&&u?o(new A("COMMAND_FAILED",`${e} timed out after ${u}ms`,{cmd:e,args:t,stdout:a,stderr:l,exitCode:c,timeoutMs:u})):0===c||r.allowFailure?n({stdout:a,stderr:l,exitCode:c,stdoutBuffer:s}):o(new A("COMMAND_FAILED",`${e} exited with code ${c}`,{cmd:e,args:t,stdout:a,stderr:l,exitCode:c,processExitError:!0}))})})}async function O(e){try{var t;let{shell:r,args:n}=(t=e,"win32"===process.platform?{shell:"cmd.exe",args:["/c","where",t]}:{shell:"bash",args:["-lc",`command -v ${t}`]}),o=await _(r,n,{allowFailure:!0});return 0===o.exitCode&&o.stdout.trim().length>0}catch{return!1}}function L(e,t,r={}){let n=l(e,t,{cwd:r.cwd,env:r.env,stdio:["pipe","pipe","pipe"],encoding:r.binaryStdout?void 0:"utf8",input:r.stdin,timeout:F(r.timeoutMs)});if(n.error){let o=n.error.code;if("ETIMEDOUT"===o)throw new A("COMMAND_FAILED",`${e} timed out after ${F(r.timeoutMs)}ms`,{cmd:e,args:t,timeoutMs:F(r.timeoutMs)},n.error);if("ENOENT"===o)throw new A("TOOL_MISSING",`${e} not found in PATH`,{cmd:e},n.error);throw new A("COMMAND_FAILED",`Failed to run ${e}`,{cmd:e,args:t},n.error)}let o=r.binaryStdout?Buffer.isBuffer(n.stdout)?n.stdout:Buffer.from(n.stdout??""):void 0,i=r.binaryStdout?"":"string"==typeof n.stdout?n.stdout:(n.stdout??"").toString(),a="string"==typeof n.stderr?n.stderr:(n.stderr??"").toString(),s=n.status??1;if(0!==s&&!r.allowFailure)throw new A("COMMAND_FAILED",`${e} exited with code ${s}`,{cmd:e,args:t,stdout:i,stderr:a,exitCode:s,processExitError:!0});return{stdout:i,stderr:a,exitCode:s,stdoutBuffer:o}}function T(e,t,r={}){c(e,t,{cwd:r.cwd,env:r.env,stdio:"ignore",detached:!0}).unref()}async function x(e,t,r={}){return new Promise((n,o)=>{let i=c(e,t,{cwd:r.cwd,env:r.env,stdio:["pipe","pipe","pipe"],detached:r.detached});r.onSpawn?.(i);let a="",s="",l=r.binaryStdout?Buffer.alloc(0):void 0;r.binaryStdout||i.stdout.setEncoding("utf8"),i.stderr.setEncoding("utf8"),void 0!==r.stdin&&i.stdin.write(r.stdin),i.stdin.end(),i.stdout.on("data",e=>{if(r.binaryStdout){l=Buffer.concat([l??Buffer.alloc(0),Buffer.isBuffer(e)?e:Buffer.from(e)]);return}let t=String(e);a+=t,r.onStdoutChunk?.(t)}),i.stderr.on("data",e=>{let t=String(e);s+=t,r.onStderrChunk?.(t)}),i.on("error",r=>{"ENOENT"===r.code?o(new A("TOOL_MISSING",`${e} not found in PATH`,{cmd:e},r)):o(new A("COMMAND_FAILED",`Failed to run ${e}`,{cmd:e,args:t},r))}),i.on("close",i=>{let c=i??1;0===c||r.allowFailure?n({stdout:a,stderr:s,exitCode:c,stdoutBuffer:l}):o(new A("COMMAND_FAILED",`${e} exited with code ${c}`,{cmd:e,args:t,stdout:a,stderr:s,exitCode:c,processExitError:!0}))})})}function C(e,t,r={}){let n=c(e,t,{cwd:r.cwd,env:r.env,stdio:["ignore","pipe","pipe"],detached:r.detached}),o="",i="";n.stdout.setEncoding("utf8"),n.stderr.setEncoding("utf8"),n.stdout.on("data",e=>{o+=e}),n.stderr.on("data",e=>{i+=e});let a=new Promise((a,s)=>{n.on("error",r=>{"ENOENT"===r.code?s(new A("TOOL_MISSING",`${e} not found in PATH`,{cmd:e},r)):s(new A("COMMAND_FAILED",`Failed to run ${e}`,{cmd:e,args:t},r))}),n.on("close",n=>{let c=n??1;0===c||r.allowFailure?a({stdout:o,stderr:i,exitCode:c}):s(new A("COMMAND_FAILED",`${e} exited with code ${c}`,{cmd:e,args:t,stdout:o,stderr:i,exitCode:c,processExitError:!0}))})});return{child:n,wait:a}}function F(e){if(!Number.isFinite(e))return;let t=Math.floor(e);if(!(t<=0))return t}let P=[/(^|[\/\s"'=])dist\/src\/daemon\.js($|[\s"'])/,/(^|[\/\s"'=])src\/daemon\.ts($|[\s"'])/];function R(e){if(!Number.isInteger(e)||e<=0)return!1;try{return process.kill(e,0),!0}catch(e){return"EPERM"===e.code}}function k(e){if(!Number.isInteger(e)||e<=0)return null;try{let t=L("ps",["-p",String(e),"-o","lstart="],{allowFailure:!0,timeoutMs:1e3});if(0!==t.exitCode)return null;let r=t.stdout.trim();return r.length>0?r:null}catch{return null}}function B(e){if(!Number.isInteger(e)||e<=0)return null;try{let t=L("ps",["-p",String(e),"-o","command="],{allowFailure:!0,timeoutMs:1e3});if(0!==t.exitCode)return null;let r=t.stdout.trim();return r.length>0?r:null}catch{return null}}function G(e,t){let r;if(!R(e))return!1;if(t){let r=k(e);if(!r||r!==t)return!1}let n=B(e);return!!n&&!!(r=n.toLowerCase().replaceAll("\\","/")).includes("agent-device")&&P.some(e=>e.test(r))}function j(e,t){try{return process.kill(e,t),!0}catch(t){let e=t.code;if("ESRCH"===e||"EPERM"===e)return!1;throw t}}async function U(e,t){if(!R(e))return!0;let r=Date.now();for(;Date.now()-r<t;)if(await new Promise(e=>setTimeout(e,50)),!R(e))return!0;return!R(e)}async function V(e,t){!G(e,t.expectedStartTime)||!j(e,"SIGTERM")||await U(e,t.termTimeoutMs)||j(e,"SIGKILL")&&await U(e,t.killTimeoutMs)}let q=100,H=new Set(["batch","replay"]);function J(e){let t;try{t=JSON.parse(e)}catch{throw new A("INVALID_ARGS","Batch steps must be valid JSON.")}if(!Array.isArray(t)||0===t.length)throw new A("INVALID_ARGS","Batch steps must be a non-empty JSON array.");return t}function W(e,t){if(!Array.isArray(e)||0===e.length)throw new A("INVALID_ARGS","batch requires a non-empty batchSteps array.");if(e.length>t)throw new A("INVALID_ARGS",`batch has ${e.length} steps; max allowed is ${t}.`);let r=[];for(let t=0;t<e.length;t+=1){let n=e[t];if(!n||"object"!=typeof n)throw new A("INVALID_ARGS",`Invalid batch step at index ${t}.`);let o="string"==typeof n.command?n.command.trim().toLowerCase():"";if(!o)throw new A("INVALID_ARGS",`Batch step ${t+1} requires command.`);if(H.has(o))throw new A("INVALID_ARGS",`Batch step ${t+1} cannot run ${o}.`);if(void 0!==n.positionals&&!Array.isArray(n.positionals))throw new A("INVALID_ARGS",`Batch step ${t+1} positionals must be an array.`);let i=n.positionals??[];if(i.some(e=>"string"!=typeof e))throw new A("INVALID_ARGS",`Batch step ${t+1} positionals must contain only strings.`);if(void 0!==n.flags&&("object"!=typeof n.flags||Array.isArray(n.flags)||!n.flags))throw new A("INVALID_ARGS",`Batch step ${t+1} flags must be an object.`);r.push({command:o,positionals:i,flags:n.flags??{}})}return r}export{default as node_net}from"node:net";export{A as AppError,q as DEFAULT_BATCH_MAX_STEPS,v as asAppError,E as buildSnapshotDisplayLines,p as createRequestId,b as displayLabel,w as emitDiagnostic,a as fileURLToPath,M as findProjectRoot,y as flushDiagnosticsToSessionFile,N as formatRole,D as formatSnapshotLine,h as getDiagnosticsMeta,G as isAgentDeviceDaemonProcess,R as isProcessAlive,t as node_crypto,r as node_fs,o as node_os,i as node_path,I as normalizeError,J as parseBatchStepsJson,s as pathToFileURL,n as promises,B as readProcessCommand,k as readProcessStartTime,$ as readVersion,_ as runCmd,C as runCmdBackground,T as runCmdDetached,x as runCmdStreaming,L as runCmdSync,c as spawn,V as stopProcessForTakeover,W as validateAndNormalizeBatchSteps,O as whichCmd,g as withDiagnosticTimer,m as withDiagnosticsScope};
|