@phnx-labs/agents-cli 1.20.17 → 1.20.19

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.
Files changed (66) hide show
  1. package/CHANGELOG.md +19 -0
  2. package/README.md +1 -1
  3. package/dist/commands/budget.d.ts +14 -0
  4. package/dist/commands/budget.js +137 -0
  5. package/dist/commands/cost.d.ts +12 -0
  6. package/dist/commands/cost.js +139 -0
  7. package/dist/commands/exec.d.ts +20 -0
  8. package/dist/commands/exec.js +382 -5
  9. package/dist/commands/secrets.d.ts +15 -0
  10. package/dist/commands/secrets.js +343 -16
  11. package/dist/commands/sessions.js +4 -0
  12. package/dist/index.js +4 -0
  13. package/dist/lib/budget/config.d.ts +9 -0
  14. package/dist/lib/budget/config.js +115 -0
  15. package/dist/lib/budget/enforce.d.ts +94 -0
  16. package/dist/lib/budget/enforce.js +151 -0
  17. package/dist/lib/budget/ledger.d.ts +61 -0
  18. package/dist/lib/budget/ledger.js +107 -0
  19. package/dist/lib/budget/preflight.d.ts +110 -0
  20. package/dist/lib/budget/preflight.js +200 -0
  21. package/dist/lib/checkpoint.d.ts +54 -0
  22. package/dist/lib/checkpoint.js +56 -0
  23. package/dist/lib/cloud/rush.js +18 -0
  24. package/dist/lib/exec.d.ts +36 -0
  25. package/dist/lib/exec.js +192 -4
  26. package/dist/lib/git.d.ts +18 -0
  27. package/dist/lib/git.js +67 -4
  28. package/dist/lib/loop.d.ts +145 -0
  29. package/dist/lib/loop.js +330 -0
  30. package/dist/lib/mcp.d.ts +7 -0
  31. package/dist/lib/mcp.js +24 -0
  32. package/dist/lib/models.d.ts +11 -0
  33. package/dist/lib/models.js +21 -0
  34. package/dist/lib/plugins.js +5 -2
  35. package/dist/lib/pricing/cost.d.ts +46 -0
  36. package/dist/lib/pricing/cost.js +71 -0
  37. package/dist/lib/pricing/index.d.ts +8 -0
  38. package/dist/lib/pricing/index.js +8 -0
  39. package/dist/lib/pricing/prices.json +138 -0
  40. package/dist/lib/pricing/table.d.ts +17 -0
  41. package/dist/lib/pricing/table.js +73 -0
  42. package/dist/lib/secrets/Agents CLI.app/Contents/CodeResources +0 -0
  43. package/dist/lib/secrets/Agents CLI.app/Contents/MacOS/Agents CLI +0 -0
  44. package/dist/lib/secrets/agent.d.ts +147 -0
  45. package/dist/lib/secrets/agent.js +500 -0
  46. package/dist/lib/secrets/bundles.d.ts +58 -7
  47. package/dist/lib/secrets/bundles.js +264 -75
  48. package/dist/lib/secrets/filestore.d.ts +82 -0
  49. package/dist/lib/secrets/filestore.js +295 -0
  50. package/dist/lib/secrets/linux.d.ts +6 -24
  51. package/dist/lib/secrets/linux.js +22 -265
  52. package/dist/lib/session/db.d.ts +40 -0
  53. package/dist/lib/session/db.js +84 -2
  54. package/dist/lib/session/discover.d.ts +2 -0
  55. package/dist/lib/session/discover.js +126 -2
  56. package/dist/lib/session/render.d.ts +2 -0
  57. package/dist/lib/session/render.js +1 -1
  58. package/dist/lib/session/types.d.ts +4 -0
  59. package/dist/lib/teams/agents.d.ts +32 -0
  60. package/dist/lib/teams/agents.js +66 -3
  61. package/dist/lib/teams/api.js +20 -0
  62. package/dist/lib/teams/parsers.js +16 -4
  63. package/dist/lib/types.d.ts +48 -0
  64. package/dist/lib/workflows.d.ts +56 -0
  65. package/dist/lib/workflows.js +72 -5
  66. package/package.json +2 -1
@@ -28,21 +28,88 @@ export function parseWorkflowFrontmatter(workflowDir) {
28
28
  const parsed = yaml.parse(frontmatter);
29
29
  if (!parsed || typeof parsed !== 'object')
30
30
  return null;
31
+ // Capability-scoping fields are wired into the run (see src/commands/exec.ts);
32
+ // coerce to string arrays defensively so a malformed `tools: foo` (scalar) or
33
+ // `tools: [Read, 3]` (mixed) never reaches buildExecCommand as a bad shape.
34
+ const asStringArray = (v) => Array.isArray(v) && v.every((x) => typeof x === 'string') ? v : undefined;
31
35
  return {
32
36
  name: parsed.name || '',
33
37
  description: parsed.description || '',
34
38
  model: parsed.model,
35
- tools: parsed.tools,
36
- skills: parsed.skills,
37
- mcpServers: parsed.mcpServers,
38
- allowedAgents: parsed.allowedAgents,
39
- secrets: parsed.secrets,
39
+ tools: asStringArray(parsed.tools),
40
+ skills: asStringArray(parsed.skills),
41
+ mcpServers: asStringArray(parsed.mcpServers),
42
+ allowedAgents: asStringArray(parsed.allowedAgents),
43
+ secrets: asStringArray(parsed.secrets),
44
+ loop: parseLoopBlock(parsed.loop),
40
45
  };
41
46
  }
42
47
  catch {
43
48
  return null;
44
49
  }
45
50
  }
51
+ /**
52
+ * Defensively coerce a frontmatter `loop:` value into a LoopConfigRaw.
53
+ *
54
+ * Mirrors the asStringArray discipline above: a malformed field is dropped to
55
+ * undefined rather than passed through, so the loop driver never sees a bad
56
+ * shape. Returns undefined when `loop:` is absent or not an object, or when no
57
+ * recognized field survives coercion (an all-garbage block is treated as
58
+ * "no loop", not "empty loop").
59
+ *
60
+ * Field rules:
61
+ * - until: only the literal `signal` is accepted; anything else dropped.
62
+ * - max_iterations: a finite positive integer; non-numbers/<=0 dropped.
63
+ * - budget: a finite positive number (tokens); non-numbers/<=0 dropped.
64
+ * - interval: a string (e.g. "0", "30m"); non-strings dropped.
65
+ */
66
+ export function parseLoopBlock(v) {
67
+ if (!v || typeof v !== 'object' || Array.isArray(v))
68
+ return undefined;
69
+ const raw = v;
70
+ const out = {};
71
+ if (raw.until === 'signal')
72
+ out.until = 'signal';
73
+ if (typeof raw.max_iterations === 'number'
74
+ && Number.isFinite(raw.max_iterations)
75
+ && Number.isInteger(raw.max_iterations)
76
+ && raw.max_iterations > 0) {
77
+ out.max_iterations = raw.max_iterations;
78
+ }
79
+ if (typeof raw.budget === 'number' && Number.isFinite(raw.budget) && raw.budget > 0) {
80
+ out.budget = raw.budget;
81
+ }
82
+ if (typeof raw.interval === 'string')
83
+ out.interval = raw.interval;
84
+ return Object.keys(out).length > 0 ? out : undefined;
85
+ }
86
+ /**
87
+ * Decide which subagent .md stems a workflow may use, given the discovered
88
+ * subagent files and the parsed `allowedAgents` frontmatter. This is the
89
+ * fail-closed security boundary for issue #324:
90
+ *
91
+ * - `allowedAgents === undefined` (field absent) -> NO restriction; allow all.
92
+ * - `allowedAgents === []` (present, empty) -> allow ZERO; copy none.
93
+ * - `allowedAgents = [a, b]` -> allow only those stems.
94
+ *
95
+ * An explicit empty array must NEVER widen to "allow all" — that would copy
96
+ * every subagent definition into the run, granting MORE access than declared.
97
+ *
98
+ * `available` are the .md filenames found in subagents/ (e.g. `security.md`).
99
+ * Returns the stems to copy and any allowedAgents entries with no matching file.
100
+ */
101
+ export function resolveAllowedSubagents(available, allowedAgents) {
102
+ const stems = available.filter(f => f.endsWith('.md')).map(f => f.replace(/\.md$/, ''));
103
+ if (allowedAgents === undefined) {
104
+ return { allowedStems: stems, missing: [] };
105
+ }
106
+ const allow = new Set(allowedAgents);
107
+ const present = new Set(stems);
108
+ return {
109
+ allowedStems: stems.filter(s => allow.has(s)),
110
+ missing: allowedAgents.filter(a => !present.has(a)),
111
+ };
112
+ }
46
113
  /** Count subagent .md files in a workflow's subagents/ directory. */
47
114
  export function countWorkflowSubagents(workflowDir) {
48
115
  const subagentsDir = path.join(workflowDir, 'subagents');
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@phnx-labs/agents-cli",
3
- "version": "1.20.17",
3
+ "version": "1.20.19",
4
4
  "description": "One CLI for all your AI coding agents - versions, config, cloud dispatch, sessions, and teams (now with first-class Grok Build CLI support)",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",
@@ -23,6 +23,7 @@
23
23
  "files": [
24
24
  "dist/**/*.js",
25
25
  "dist/**/*.d.ts",
26
+ "dist/**/*.json",
26
27
  "dist/lib/secrets/Agents CLI.app/**",
27
28
  "scripts/postinstall.js",
28
29
  "scripts/install-helper.js",