shakers-cli 0.16.0 → 0.18.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.
Files changed (69) hide show
  1. package/README.md +21 -6
  2. package/bin/ai-usage.js +31 -12
  3. package/bin/command-audit-worker.js +19 -0
  4. package/bin/login.js +4 -8
  5. package/bin/mcp.js +32 -21
  6. package/bin/register.js +12 -30
  7. package/bin/shakers-cli.js +15 -10
  8. package/package.json +1 -1
  9. package/src/account-marker.js +40 -0
  10. package/src/account-trace.js +23 -0
  11. package/src/agents-client.js +1 -0
  12. package/src/ai-usage-review.js +103 -0
  13. package/src/auth-client.js +7 -107
  14. package/src/auth-session-store.js +12 -11
  15. package/src/backend-request.js +3 -24
  16. package/src/cli-skill.js +77 -0
  17. package/src/command-audit.js +47 -4
  18. package/src/config.js +2 -16
  19. package/src/consent-flow.js +9 -3
  20. package/src/detect-repos.js +4 -8
  21. package/src/detectors.js +23 -0
  22. package/src/device-auth-store.js +2 -2
  23. package/src/device-login.js +11 -9
  24. package/src/env-paths.js +9 -1
  25. package/src/i18n.js +186 -102
  26. package/src/mcp-ai-usage-result-tool.js +38 -14
  27. package/src/mcp-ai-usage-tool.js +317 -172
  28. package/src/mcp-choice.js +171 -34
  29. package/src/mcp-detector.js +26 -2
  30. package/src/mcp-device-login-tools.js +40 -8
  31. package/src/mcp-install.js +292 -53
  32. package/src/mcp-instructions.js +43 -17
  33. package/src/mcp-onboarding-tools.js +1 -3
  34. package/src/mcp-prompts.js +8 -6
  35. package/src/mcp-register-tools.js +25 -14
  36. package/src/mcp-role-tools.js +59 -18
  37. package/src/mcp-server-name.js +7 -0
  38. package/src/mcp-server.js +35 -7
  39. package/src/mcp-signup-client.js +3 -6
  40. package/src/mcp-signup-flow.js +389 -0
  41. package/src/mcp-signup-tools.js +250 -133
  42. package/src/onboarding-flow.js +72 -146
  43. package/src/onboarding-funnel.js +46 -6
  44. package/src/opencode-sessions.js +92 -0
  45. package/src/profile-agents.js +26 -0
  46. package/src/render-report-text.js +1 -1
  47. package/src/report-gating.js +4 -2
  48. package/src/report-store.js +7 -2
  49. package/src/roles-flow.js +8 -5
  50. package/src/saved-positions-flow.js +3 -3
  51. package/src/scanner.js +104 -12
  52. package/src/session-gate.js +1 -4
  53. package/src/session-normalizers.js +114 -8
  54. package/src/session-refresh.js +5 -16
  55. package/src/session-scan.js +167 -22
  56. package/src/share-consent-state.js +2 -2
  57. package/src/share-payload.js +4 -1
  58. package/src/share.js +2 -2
  59. package/src/signup-client.js +12 -39
  60. package/src/signup-copy.js +545 -58
  61. package/src/skill-install.js +102 -0
  62. package/src/stdin-ask.js +13 -1
  63. package/src/tier-engine.js +14 -2
  64. package/src/trust-narration.js +32 -0
  65. package/src/usage-run-steps.js +68 -6
  66. package/src/usage-scan.js +11 -8
  67. package/src/brand-svg.js +0 -9
  68. package/src/inter-fonts.js +0 -6
  69. package/src/mcp-auth-form.js +0 -480
@@ -3,7 +3,8 @@
3
3
  const FLOOR_METHOD = 'floor';
4
4
  const FLOOR_CODE = 'other-1';
5
5
  const POLL_INTERVAL_MS = 5000;
6
- const POLL_CAP_MS = 90000;
6
+ // With the last inventory request (its own timeout) this answers within ~45 s, under Claude Desktop's ~60 s cut.
7
+ const POLL_CAP_MS = 30000;
7
8
  const INVENTORY_TIMEOUT_MS = 15000;
8
9
 
9
10
  const RESULT_INPUT_SCHEMA = { type: 'object', properties: {} };
@@ -52,6 +53,8 @@ async function pollClassifiedInventory({
52
53
  }
53
54
  }
54
55
 
56
+ const RESULT_MESSAGE = 'Print relayVerbatim word for word: the result in "My work with AI", what it means and how to ask for a human review.';
57
+ const PROFILE_PENDING_MESSAGE = 'The profile result is not ready yet: call ai_usage_result again in a few minutes.';
55
58
  const READY_MESSAGE = 'Shakers finished classifying the agents.';
56
59
  const PENDING_MESSAGE = 'Shakers is still classifying the agents — this is normal, call ai_usage_result again shortly to keep waiting.';
57
60
 
@@ -65,9 +68,16 @@ function makeAiUsageResultTool(deps = {}) {
65
68
  now = () => Date.now(),
66
69
  intervalMs = POLL_INTERVAL_MS,
67
70
  capMs = POLL_CAP_MS,
71
+ resolveAiProfilePreview = require('./ai-profile-preview').resolveAiProfilePreview,
72
+ getAiProfileEndpoint = require('./config').getAiProfileEndpoint,
73
+ ensureFreshSession = require('./session-refresh').ensureFreshSession,
74
+ aiProfileWaitMs = 30000,
75
+ resultText = require('./ai-usage-review').resultText,
76
+ lang = () => require('./signup-language').signupLanguage(require('./i18n').detectFlowLang()),
68
77
  } = deps;
69
78
 
70
- async function handler() {
79
+ // `explained` comes only from the sign-up, whose review already explained the axes and how to disagree.
80
+ async function handler(args = {}) {
71
81
  const session = loadAuthSession();
72
82
  if (sessionStatus(session) !== 'active') {
73
83
  throw new Error('no active Shakers session — sign in with social_signin_start (or run `shakers login`) first.');
@@ -77,27 +87,41 @@ function makeAiUsageResultTool(deps = {}) {
77
87
  throw new Error('discovered-inventory endpoint is not configured (set SHAKERS_CLI_INGEST_ENDPOINT).');
78
88
  }
79
89
 
80
- const result = await pollClassifiedInventory({
81
- accessToken: session.accessToken,
82
- endpoint,
83
- requestDiscoveredInventory,
84
- sleep,
85
- now,
86
- intervalMs,
87
- capMs,
88
- });
90
+ const [result, aiProfile] = await Promise.all([
91
+ pollClassifiedInventory({
92
+ accessToken: session.accessToken,
93
+ endpoint,
94
+ requestDiscoveredInventory,
95
+ sleep,
96
+ now,
97
+ intervalMs,
98
+ capMs,
99
+ }),
100
+ resolveAiProfilePreview(
101
+ { session, endpoint: getAiProfileEndpoint(), timeoutMs: aiProfileWaitMs },
102
+ {
103
+ refreshToken: async () => {
104
+ const fresh = await ensureFreshSession(process.env);
105
+ return fresh ? { accessToken: fresh.accessToken, hubAccessToken: fresh.hubAccessToken } : null;
106
+ },
107
+ },
108
+ ).catch(() => ({ status: 'unavailable', preview: null })),
109
+ ]);
110
+ const profileReady = aiProfile.status === 'ready';
89
111
  return {
90
112
  ...result,
91
- message: result.status === 'ready' ? READY_MESSAGE : PENDING_MESSAGE,
113
+ aiProfile,
114
+ relayVerbatim: resultText(lang(), profileReady ? aiProfile.preview : null, { explained: args.explained === true }),
115
+ message: `${RESULT_MESSAGE} ${result.status === 'ready' ? READY_MESSAGE : PENDING_MESSAGE}${profileReady ? '' : ` ${PROFILE_PENDING_MESSAGE}`}`,
92
116
  };
93
117
  }
94
118
 
95
119
  return {
96
120
  name: 'ai_usage_result',
97
121
  title: 'Results of your AI analysis',
98
- description: 'Fetches from Shakers the description of each AI agent found in the analysis you approved. It reads nothing on this computer.',
122
+ description: 'Fetches from Shakers the result of the AI analysis you approved, what it means, and the description of each AI agent found. It reads nothing on this computer.',
99
123
  guidance:
100
- "Retrieve the enriched Shakers classification for the talent's agents after ai_usage. Shakers classifies agents and writes their descriptions server-side (no client LLM), so this reads the result: per agent { name, tools, model, category, role, level, code, whatItDoes }. Session-keyed, no arguments. Server-side classification can take a few minutes, so this does a bounded internal poll (~90s max, never a long-held call): returns { status: 'ready', agents } once every agent has been classified, or { status: 'pending', agents } while Shakers is still processing (call it again to keep waiting — 'pending' is normal progress, not an error). Present agents to the talent by NAME and category/role only; the `code` field is an internal handle for add_agent, never show it. Requires an active session.",
124
+ "Retrieve the result after an approved upload: relayVerbatim is the 'My work with AI' result with its levels and explanation in plain words, and how to ask for a human review; print it word for word. It also returns the enriched Shakers classification for the talent's agents. Shakers classifies agents and writes their descriptions server-side (no client LLM), so this reads the result: per agent { name, tools, model, category, role, level, code, whatItDoes }. Session-keyed, no arguments. Server-side classification can take a few minutes, so this does a bounded internal poll (~30 s, never a long-held call): returns { status: 'ready', agents } once every agent has been classified, or { status: 'pending', agents } while Shakers is still processing (call it again to keep waiting — 'pending' is normal progress, not an error). Present agents to the talent by NAME and category/role only; the `code` field is an internal handle for add_agent, never show it. Requires an active session.",
101
125
  inputSchema: RESULT_INPUT_SCHEMA,
102
126
  handler,
103
127
  };