@phnx-labs/agents-cli 1.22.60 → 1.22.61

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 (85) hide show
  1. package/CHANGELOG.md +49 -0
  2. package/dist/cli/command-registry.d.ts +1 -0
  3. package/dist/cli/command-registry.js +2 -0
  4. package/dist/commands/browser.js +9 -4
  5. package/dist/commands/doctor.js +1 -1
  6. package/dist/commands/exec.js +35 -1
  7. package/dist/commands/harness-hooks.d.ts +55 -0
  8. package/dist/commands/harness-hooks.js +104 -0
  9. package/dist/commands/harness-wizard.d.ts +33 -14
  10. package/dist/commands/harness-wizard.js +53 -23
  11. package/dist/commands/harness.d.ts +14 -0
  12. package/dist/commands/harness.js +86 -5
  13. package/dist/commands/reminders.d.ts +9 -0
  14. package/dist/commands/reminders.js +49 -0
  15. package/dist/commands/run-account-picker.d.ts +14 -0
  16. package/dist/commands/run-account-picker.js +13 -0
  17. package/dist/commands/teams.d.ts +1 -1
  18. package/dist/commands/teams.js +9 -3
  19. package/dist/index.js +9 -0
  20. package/dist/lib/accounting/rotate.d.ts +63 -0
  21. package/dist/lib/accounting/rotate.js +229 -13
  22. package/dist/lib/browser/drivers/local.d.ts +11 -0
  23. package/dist/lib/browser/drivers/local.js +26 -0
  24. package/dist/lib/browser/profiles.js +8 -6
  25. package/dist/lib/browser/service.d.ts +12 -8
  26. package/dist/lib/browser/service.js +38 -10
  27. package/dist/lib/claude-statusline.d.ts +14 -1
  28. package/dist/lib/claude-statusline.js +27 -2
  29. package/dist/lib/daemon/runner.js +17 -2
  30. package/dist/lib/devices/doctor-findings.d.ts +1 -1
  31. package/dist/lib/devices/doctor-findings.js +22 -4
  32. package/dist/lib/doctor-diff.d.ts +21 -5
  33. package/dist/lib/doctor-diff.js +242 -76
  34. package/dist/lib/feed/events.d.ts +1 -1
  35. package/dist/lib/feed/events.js +25 -16
  36. package/dist/lib/github/gh-overload.d.ts +58 -0
  37. package/dist/lib/github/gh-overload.js +246 -0
  38. package/dist/lib/github/rest.d.ts +64 -0
  39. package/dist/lib/github/rest.js +111 -0
  40. package/dist/lib/harness-connection-test.d.ts +57 -0
  41. package/dist/lib/harness-connection-test.js +80 -0
  42. package/dist/lib/heal.js +8 -3
  43. package/dist/lib/installations/shims.d.ts +22 -0
  44. package/dist/lib/installations/shims.js +104 -0
  45. package/dist/lib/linear-project-counts.js +8 -0
  46. package/dist/lib/linear-rate-limit.d.ts +26 -0
  47. package/dist/lib/linear-rate-limit.js +163 -0
  48. package/dist/lib/mcp.d.ts +9 -0
  49. package/dist/lib/mcp.js +37 -1
  50. package/dist/lib/open-url.js +5 -3
  51. package/dist/lib/permissions.d.ts +28 -0
  52. package/dist/lib/permissions.js +156 -1
  53. package/dist/lib/refresh.js +9 -1
  54. package/dist/lib/reminders.d.ts +29 -0
  55. package/dist/lib/reminders.js +88 -0
  56. package/dist/lib/resource-content-diff.d.ts +33 -0
  57. package/dist/lib/resource-content-diff.js +103 -0
  58. package/dist/lib/rules/compile.d.ts +7 -0
  59. package/dist/lib/rules/compile.js +7 -1
  60. package/dist/lib/session/active.d.ts +41 -4
  61. package/dist/lib/session/active.js +58 -7
  62. package/dist/lib/session/host-link.d.ts +22 -0
  63. package/dist/lib/session/host-link.js +40 -4
  64. package/dist/lib/session/trajectory.d.ts +42 -0
  65. package/dist/lib/session/trajectory.js +46 -27
  66. package/dist/lib/ssh-exec.d.ts +30 -0
  67. package/dist/lib/ssh-exec.js +37 -5
  68. package/dist/lib/startup/command-registry.js +1 -1
  69. package/dist/lib/subagents-registry.d.ts +18 -0
  70. package/dist/lib/subagents-registry.js +79 -0
  71. package/dist/lib/teams/agents.d.ts +12 -0
  72. package/dist/lib/teams/agents.js +51 -0
  73. package/dist/lib/traces/schema2-build.d.ts +85 -0
  74. package/dist/lib/traces/schema2-build.js +637 -0
  75. package/dist/lib/traces/schema2-danger.d.ts +36 -0
  76. package/dist/lib/traces/schema2-danger.js +185 -0
  77. package/dist/lib/traces/schema2.d.ts +149 -0
  78. package/dist/lib/traces/schema2.js +20 -0
  79. package/dist/lib/traces/sync.d.ts +93 -0
  80. package/dist/lib/traces/sync.js +75 -22
  81. package/dist/lib/traces/worker-template.js +5 -0
  82. package/dist/lib/uninstall.js +10 -1
  83. package/dist/lib/workflows.d.ts +11 -0
  84. package/dist/lib/workflows.js +67 -8
  85. package/package.json +1 -1
@@ -19,7 +19,7 @@ import * as fs from 'fs';
19
19
  import * as os from 'os';
20
20
  import * as path from 'path';
21
21
  import { AGENTS, ALL_AGENT_IDS } from './agents.js';
22
- import { getAgentConfigPath, getConfigSymlinkVersion, stripShimPathLines, releaseAdoptedLauncher, } from './installations/shims.js';
22
+ import { getAgentConfigPath, getConfigSymlinkVersion, stripShimPathLines, releaseAdoptedLauncher, removeGhOverloadShim, } from './installations/shims.js';
23
23
  import { moveDirCrossDevice, copyDirStrippingAgentsSymlinks } from './config-transfer.js';
24
24
  import { getUserAgentsDir, getBackupsDir, getHistoryDir, getShimsDir, getLegacySystemAgentsDir, } from './state.js';
25
25
  /** Home dir honoring the AGENTS_REAL_HOME test/override, mirroring shims.ts. */
@@ -252,6 +252,15 @@ export function executeUninstall(plan, opts) {
252
252
  result.errors.push(`launcher ${cli}: ${err.message}`);
253
253
  }
254
254
  }
255
+ // 3b. Remove the gh overload shim explicitly, so a real gh returns even if the
256
+ // shims dir itself is left in place. (The shim self-heals to real gh regardless,
257
+ // but leaving no orphan is cleaner — PHNX-3501.)
258
+ try {
259
+ removeGhOverloadShim();
260
+ }
261
+ catch (err) {
262
+ result.errors.push(`gh overload shim: ${err.message}`);
263
+ }
255
264
  // 4. Strip the shim directory from the user's PATH across all rc files.
256
265
  const shimsDir = getShimsDir();
257
266
  for (const rc of plan.rcFiles) {
@@ -375,6 +375,17 @@ export declare function removeWorkflow(name: string): {
375
375
  };
376
376
  /** List workflow names synced into a specific agent version home. */
377
377
  export declare function listWorkflowsForAgent(agent: AgentId, versionHome: string): string[];
378
+ /**
379
+ * True when workflow `name` materialized in `agent`'s version home byte-matches
380
+ * what the writer would produce NOW from `sourcePath` — the content-drift
381
+ * predicate `agents doctor` uses. Layout-aware per the same per-harness map the
382
+ * writer (`syncWorkflowToVersion`) and detector use: Claude/default copy the
383
+ * whole WORKFLOW.md tree (recursive dir compare); Kimi/Antigravity/OpenClaw/Grok
384
+ * render one transformed file; Goose renders a recipe YAML. Antigravity's target
385
+ * is the shared HOME-global dir, not a per-version path. Returns false when the
386
+ * home copy is absent (surfaced as `missing` at the name level, not here).
387
+ */
388
+ export declare function workflowContentMatches(agent: AgentId, versionHome: string, name: string, sourcePath: string): boolean;
378
389
  /** Copy a workflow directory into a version home at {versionHome}/workflows/<name>/. */
379
390
  export declare function syncWorkflowToVersion(workflowPath: string, name: string, agent: AgentId, versionHome: string): {
380
391
  success: boolean;
@@ -12,6 +12,7 @@ import * as yaml from 'yaml';
12
12
  import { capableAgents, supports } from './capabilities.js';
13
13
  import { getProjectAgentsDir, getSystemWorkflowsDir, getUserWorkflowsDir, getTrashWorkflowsDir, getEnabledExtraRepos, getPluginsDir, getSystemPluginsDir, getProjectPluginsDir, } from './state.js';
14
14
  import { listInstalledVersions, getVersionHomePath } from './installations/versions.js';
15
+ import { dirsContentMatch, normalizeResourceContent } from './resource-content-diff.js';
15
16
  /**
16
17
  * Hard upper bound on items a single `for_each` expands, absent an explicit
17
18
  * `max_items`. A guard against a runaway producer spawning unbounded teammates
@@ -937,14 +938,16 @@ function writeGooseSubrecipe(workflowPath, subrecipeName, destDir) {
937
938
  fs.mkdirSync(destDir, { recursive: true });
938
939
  fs.writeFileSync(path.join(destDir, `${subrecipeName}.yaml`), yaml.stringify(recipe), 'utf-8');
939
940
  }
940
- function syncWorkflowToGooseRecipe(workflowPath, name, versionHome) {
941
+ /**
942
+ * Render the main Goose recipe YAML for a workflow — the exact bytes
943
+ * `syncWorkflowToGooseRecipe` writes to `<name>.yaml`. Extracted so the sync
944
+ * writer and the doctor content-drift check (`workflowContentMatches`) render
945
+ * from ONE source and can never disagree. Returns null on invalid frontmatter.
946
+ */
947
+ function renderGooseRecipeYaml(workflowPath, name) {
941
948
  const frontmatter = parseWorkflowFrontmatter(workflowPath);
942
- if (!frontmatter) {
943
- return { success: false, error: `Workflow '${name}' has invalid WORKFLOW.md frontmatter` };
944
- }
945
- const recipesDir = path.join(versionHome, '.config', 'goose', 'recipes');
946
- const recipePath = path.join(recipesDir, `${name}.yaml`);
947
- const subrecipesDir = path.join(recipesDir, `${name}.subrecipes`);
949
+ if (!frontmatter)
950
+ return null;
948
951
  const body = readWorkflowBody(workflowPath) || frontmatter.description || name;
949
952
  const subagents = selectedWorkflowSubagents(workflowPath, frontmatter.allowedAgents);
950
953
  const recipe = {
@@ -964,6 +967,21 @@ function syncWorkflowToGooseRecipe(workflowPath, name, versionHome) {
964
967
  description: `Workflow subrecipe ${subagentName}`,
965
968
  }));
966
969
  }
970
+ return yaml.stringify(recipe);
971
+ }
972
+ function syncWorkflowToGooseRecipe(workflowPath, name, versionHome) {
973
+ const frontmatter = parseWorkflowFrontmatter(workflowPath);
974
+ if (!frontmatter) {
975
+ return { success: false, error: `Workflow '${name}' has invalid WORKFLOW.md frontmatter` };
976
+ }
977
+ const recipesDir = path.join(versionHome, '.config', 'goose', 'recipes');
978
+ const recipePath = path.join(recipesDir, `${name}.yaml`);
979
+ const subrecipesDir = path.join(recipesDir, `${name}.subrecipes`);
980
+ const subagents = selectedWorkflowSubagents(workflowPath, frontmatter.allowedAgents);
981
+ const recipeYaml = renderGooseRecipeYaml(workflowPath, name);
982
+ if (recipeYaml == null) {
983
+ return { success: false, error: `Workflow '${name}' has invalid WORKFLOW.md frontmatter` };
984
+ }
967
985
  try {
968
986
  fs.mkdirSync(recipesDir, { recursive: true });
969
987
  if (fs.existsSync(subrecipesDir)) {
@@ -972,13 +990,54 @@ function syncWorkflowToGooseRecipe(workflowPath, name, versionHome) {
972
990
  for (const subagentName of subagents) {
973
991
  writeGooseSubrecipe(workflowPath, subagentName, subrecipesDir);
974
992
  }
975
- fs.writeFileSync(recipePath, yaml.stringify(recipe), 'utf-8');
993
+ fs.writeFileSync(recipePath, recipeYaml, 'utf-8');
976
994
  return { success: true };
977
995
  }
978
996
  catch (err) {
979
997
  return { success: false, error: err.message };
980
998
  }
981
999
  }
1000
+ /**
1001
+ * True when workflow `name` materialized in `agent`'s version home byte-matches
1002
+ * what the writer would produce NOW from `sourcePath` — the content-drift
1003
+ * predicate `agents doctor` uses. Layout-aware per the same per-harness map the
1004
+ * writer (`syncWorkflowToVersion`) and detector use: Claude/default copy the
1005
+ * whole WORKFLOW.md tree (recursive dir compare); Kimi/Antigravity/OpenClaw/Grok
1006
+ * render one transformed file; Goose renders a recipe YAML. Antigravity's target
1007
+ * is the shared HOME-global dir, not a per-version path. Returns false when the
1008
+ * home copy is absent (surfaced as `missing` at the name level, not here).
1009
+ */
1010
+ export function workflowContentMatches(agent, versionHome, name, sourcePath) {
1011
+ const root = workflowTargetRoot(agent, versionHome);
1012
+ const renderedMatches = (homePath, expected) => {
1013
+ let actual;
1014
+ try {
1015
+ actual = fs.readFileSync(homePath, 'utf-8');
1016
+ }
1017
+ catch {
1018
+ return false;
1019
+ }
1020
+ return normalizeResourceContent(actual) === normalizeResourceContent(expected);
1021
+ };
1022
+ switch (agent) {
1023
+ case 'kimi':
1024
+ return renderedMatches(path.join(root, name, 'SKILL.md'), transformWorkflowForKimi(sourcePath, name));
1025
+ case 'antigravity':
1026
+ return renderedMatches(path.join(root, `${name}.md`), transformWorkflowForAntigravity(sourcePath, name));
1027
+ case 'openclaw':
1028
+ return renderedMatches(path.join(root, `${name}.lobster`), transformWorkflowForOpenClaw(sourcePath, name));
1029
+ case 'grok':
1030
+ return renderedMatches(path.join(root, `${name}.rhai`), transformWorkflowForGrok(sourcePath, name));
1031
+ case 'goose': {
1032
+ const expected = renderGooseRecipeYaml(sourcePath, name);
1033
+ if (expected == null)
1034
+ return false;
1035
+ return renderedMatches(path.join(versionHome, '.config', 'goose', 'recipes', `${name}.yaml`), expected);
1036
+ }
1037
+ default:
1038
+ return dirsContentMatch(sourcePath, path.join(root, name));
1039
+ }
1040
+ }
982
1041
  /** Copy a workflow directory into a version home at {versionHome}/workflows/<name>/. */
983
1042
  export function syncWorkflowToVersion(workflowPath, name, agent, versionHome) {
984
1043
  if (agent === 'goose') {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@phnx-labs/agents-cli",
3
- "version": "1.22.60",
3
+ "version": "1.22.61",
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",