@skillrecordings/cli 0.16.1 → 0.17.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/dist/index.js CHANGED
@@ -20,8 +20,9 @@ import {
20
20
  runPipeline,
21
21
  validate,
22
22
  validateSync
23
- } from "./chunk-A5RBWKVF.js";
23
+ } from "./chunk-J4IC3GC3.js";
24
24
  import "./chunk-HK3PEWFD.js";
25
+ import "./chunk-WYKL32C3.js";
25
26
  import {
26
27
  createFilterStats,
27
28
  formatFilterStats,
@@ -39,20 +40,26 @@ import {
39
40
  getApp,
40
41
  getOutcomeHistory,
41
42
  getRedis
42
- } from "./chunk-L6YTBYNV.js";
43
+ } from "./chunk-IR6KG25Y.js";
43
44
  import "./chunk-KEV3QKXP.js";
44
- import "./chunk-ZNF7XD2S.js";
45
- import {
46
- upsertVector
47
- } from "./chunk-H3D6VCME.js";
48
- import "./chunk-F4EM72IH.js";
49
- import "./chunk-WYKL32C3.js";
50
45
  import {
51
46
  MemoryService,
52
47
  VotingService,
53
48
  calculateConfidence
54
49
  } from "./chunk-MLNDSBZ4.js";
50
+ import "./chunk-ZNF7XD2S.js";
51
+ import {
52
+ upsertVector
53
+ } from "./chunk-H3D6VCME.js";
55
54
  import "./chunk-MG37YDAK.js";
55
+ import "./chunk-F4EM72IH.js";
56
+ import {
57
+ addShellIntegration,
58
+ autoBootstrapKeychain,
59
+ getKeychainStatus,
60
+ isKeychainSupported,
61
+ storeInKeychain
62
+ } from "./chunk-7SQU7KCI.js";
56
63
  import {
57
64
  OnePasswordProvider,
58
65
  SECRET_REFS,
@@ -74630,19 +74637,43 @@ async function decryptEnvFile(encryptedPath) {
74630
74637
  }
74631
74638
  }
74632
74639
  async function getAgeKeyFrom1Password() {
74633
- if (!process.env.OP_SERVICE_ACCOUNT_TOKEN) {
74634
- return null;
74640
+ if (process.env.SKILL_AGE_KEY) {
74641
+ return process.env.SKILL_AGE_KEY;
74635
74642
  }
74636
74643
  try {
74637
- const { OnePasswordProvider: OnePasswordProvider2 } = await import("./secrets-MGVPGMFJ.js");
74638
- const op = new OnePasswordProvider2();
74639
- if (!await op.isAvailable()) {
74640
- return null;
74644
+ const { getFromKeychain, storeInKeychain: storeInKeychain2, autoBootstrapKeychain: autoBootstrapKeychain2 } = await import("./keychain-IEZHT5WN.js");
74645
+ const fromKeychain = getFromKeychain("age-private-key");
74646
+ if (fromKeychain) return fromKeychain;
74647
+ let opToken = process.env.OP_SERVICE_ACCOUNT_TOKEN;
74648
+ if (!opToken) {
74649
+ opToken = autoBootstrapKeychain2() ?? void 0;
74650
+ }
74651
+ if (opToken) {
74652
+ const originalEnv = process.env.OP_SERVICE_ACCOUNT_TOKEN;
74653
+ process.env.OP_SERVICE_ACCOUNT_TOKEN = opToken;
74654
+ try {
74655
+ const { OnePasswordProvider: OnePasswordProvider2 } = await import("./secrets-MGVPGMFJ.js");
74656
+ const op = new OnePasswordProvider2();
74657
+ if (await op.isAvailable()) {
74658
+ const key = await op.resolve(
74659
+ "op://Support/skill-cli-age-key/private_key"
74660
+ );
74661
+ if (key) {
74662
+ storeInKeychain2("age-private-key", key);
74663
+ return key;
74664
+ }
74665
+ }
74666
+ } finally {
74667
+ if (originalEnv) {
74668
+ process.env.OP_SERVICE_ACCOUNT_TOKEN = originalEnv;
74669
+ } else {
74670
+ delete process.env.OP_SERVICE_ACCOUNT_TOKEN;
74671
+ }
74672
+ }
74641
74673
  }
74642
- return await op.resolve("op://Support/skill-cli-age-key/private_key");
74643
74674
  } catch {
74644
- return null;
74645
74675
  }
74676
+ return null;
74646
74677
  }
74647
74678
  async function loadShippedDefaults(cliRoot2) {
74648
74679
  const encryptedPath = resolve(cliRoot2, ".env.encrypted");
@@ -75667,6 +75698,74 @@ function registerAuthCommands(program3, usageState2) {
75667
75698
  // src/commands/axiom/index.ts
75668
75699
  init_esm_shims();
75669
75700
 
75701
+ // src/core/spinner.ts
75702
+ init_esm_shims();
75703
+ var FRAMES = ["\u280B", "\u2819", "\u2839", "\u2838", "\u283C", "\u2834", "\u2826", "\u2827", "\u2807", "\u280F"];
75704
+ var INTERVAL = 80;
75705
+ function createSpinner() {
75706
+ const isTTY = process.stderr.isTTY && !process.env.CI;
75707
+ let interval = null;
75708
+ let frameIndex = 0;
75709
+ let currentMessage = "";
75710
+ const clear = () => {
75711
+ if (!isTTY) return;
75712
+ process.stderr.write("\r\x1B[K");
75713
+ };
75714
+ const render3 = () => {
75715
+ if (!isTTY) return;
75716
+ const frame = FRAMES[frameIndex];
75717
+ process.stderr.write(`\r${frame} ${currentMessage}`);
75718
+ frameIndex = (frameIndex + 1) % FRAMES.length;
75719
+ };
75720
+ const start = (message = "Loading...") => {
75721
+ if (!isTTY) return;
75722
+ currentMessage = message;
75723
+ frameIndex = 0;
75724
+ render3();
75725
+ interval = setInterval(render3, INTERVAL);
75726
+ };
75727
+ const update2 = (message) => {
75728
+ currentMessage = message;
75729
+ if (isTTY && !interval) {
75730
+ render3();
75731
+ }
75732
+ };
75733
+ const stop = () => {
75734
+ if (interval) {
75735
+ clearInterval(interval);
75736
+ interval = null;
75737
+ }
75738
+ clear();
75739
+ };
75740
+ const succeed = (message) => {
75741
+ stop();
75742
+ if (isTTY && message) {
75743
+ process.stderr.write(`\u2713 ${message}
75744
+ `);
75745
+ }
75746
+ };
75747
+ const fail = (message) => {
75748
+ stop();
75749
+ if (isTTY && message) {
75750
+ process.stderr.write(`\u2717 ${message}
75751
+ `);
75752
+ }
75753
+ };
75754
+ return { start, update: update2, stop, succeed, fail };
75755
+ }
75756
+ async function withSpinner(message, fn) {
75757
+ const spinner = createSpinner();
75758
+ spinner.start(message);
75759
+ try {
75760
+ const result = await fn();
75761
+ spinner.stop();
75762
+ return result;
75763
+ } catch (error) {
75764
+ spinner.stop();
75765
+ throw error;
75766
+ }
75767
+ }
75768
+
75670
75769
  // src/lib/axiom-client.ts
75671
75770
  init_esm_shims();
75672
75771
  import { Axiom } from "@axiomhq/js";
@@ -76365,10 +76464,13 @@ async function runQuery(ctx, apl, options) {
76365
76464
  const { startTime, endTime } = parseTimeRange(options.since ?? "24h");
76366
76465
  const outputJson = options.json === true || ctx.format === "json";
76367
76466
  try {
76368
- const result = await client.query(apl, {
76369
- startTime: startTime.toISOString(),
76370
- endTime: endTime.toISOString()
76371
- });
76467
+ const result = await withSpinner(
76468
+ "Running query...",
76469
+ () => client.query(apl, {
76470
+ startTime: startTime.toISOString(),
76471
+ endTime: endTime.toISOString()
76472
+ })
76473
+ );
76372
76474
  if (outputJson) {
76373
76475
  ctx.output.data(result);
76374
76476
  return;
@@ -76412,10 +76514,13 @@ async function listAgentRuns(ctx, options) {
76412
76514
  | sort by _time desc
76413
76515
  | limit ${limit2}`;
76414
76516
  try {
76415
- const result = await client.query(apl, {
76416
- startTime: startTime.toISOString(),
76417
- endTime: endTime.toISOString()
76418
- });
76517
+ const result = await withSpinner(
76518
+ "Loading agent runs...",
76519
+ () => client.query(apl, {
76520
+ startTime: startTime.toISOString(),
76521
+ endTime: endTime.toISOString()
76522
+ })
76523
+ );
76419
76524
  const matches = result.matches ?? [];
76420
76525
  if (outputJson) {
76421
76526
  ctx.output.data(matches.map((m) => m.data));
@@ -76469,10 +76574,13 @@ async function listErrors(ctx, options) {
76469
76574
  | sort by _time desc
76470
76575
  | limit ${limit2}`;
76471
76576
  try {
76472
- const result = await client.query(apl, {
76473
- startTime: startTime.toISOString(),
76474
- endTime: endTime.toISOString()
76475
- });
76577
+ const result = await withSpinner(
76578
+ "Loading errors...",
76579
+ () => client.query(apl, {
76580
+ startTime: startTime.toISOString(),
76581
+ endTime: endTime.toISOString()
76582
+ })
76583
+ );
76476
76584
  const matches = result.matches ?? [];
76477
76585
  if (outputJson) {
76478
76586
  ctx.output.data(matches.map((m) => m.data));
@@ -76509,10 +76617,13 @@ async function getConversation(ctx, conversationId, options) {
76509
76617
  | where conversationId == '${conversationId}'
76510
76618
  | sort by _time asc`;
76511
76619
  try {
76512
- const result = await client.query(apl, {
76513
- startTime: startTime.toISOString(),
76514
- endTime: endTime.toISOString()
76515
- });
76620
+ const result = await withSpinner(
76621
+ "Loading conversation...",
76622
+ () => client.query(apl, {
76623
+ startTime: startTime.toISOString(),
76624
+ endTime: endTime.toISOString()
76625
+ })
76626
+ );
76516
76627
  const matches = result.matches ?? [];
76517
76628
  if (outputJson) {
76518
76629
  ctx.output.data(
@@ -76568,10 +76679,13 @@ async function getClassificationStats(ctx, options) {
76568
76679
  apl += `
76569
76680
  | summarize count = count() by category, complexity`;
76570
76681
  try {
76571
- const result = await client.query(apl, {
76572
- startTime: startTime.toISOString(),
76573
- endTime: endTime.toISOString()
76574
- });
76682
+ const result = await withSpinner(
76683
+ "Loading classifications...",
76684
+ () => client.query(apl, {
76685
+ startTime: startTime.toISOString(),
76686
+ endTime: endTime.toISOString()
76687
+ })
76688
+ );
76575
76689
  const buckets = result.buckets?.totals ?? [];
76576
76690
  if (outputJson) {
76577
76691
  ctx.output.data(buckets);
@@ -76631,10 +76745,13 @@ async function listWorkflowSteps(ctx, options) {
76631
76745
  | sort by _time desc
76632
76746
  | limit ${limit2}`;
76633
76747
  try {
76634
- const result = await client.query(apl, {
76635
- startTime: startTime.toISOString(),
76636
- endTime: endTime.toISOString()
76637
- });
76748
+ const result = await withSpinner(
76749
+ "Loading workflow steps...",
76750
+ () => client.query(apl, {
76751
+ startTime: startTime.toISOString(),
76752
+ endTime: endTime.toISOString()
76753
+ })
76754
+ );
76638
76755
  const matches = result.matches ?? [];
76639
76756
  if (outputJson) {
76640
76757
  ctx.output.data(matches.map((m) => m.data));
@@ -76677,10 +76794,13 @@ async function listApprovals(ctx, options) {
76677
76794
  | sort by _time desc
76678
76795
  | limit ${limit2}`;
76679
76796
  try {
76680
- const result = await client.query(apl, {
76681
- startTime: startTime.toISOString(),
76682
- endTime: endTime.toISOString()
76683
- });
76797
+ const result = await withSpinner(
76798
+ "Loading approvals...",
76799
+ () => client.query(apl, {
76800
+ startTime: startTime.toISOString(),
76801
+ endTime: endTime.toISOString()
76802
+ })
76803
+ );
76684
76804
  const matches = result.matches ?? [];
76685
76805
  if (outputJson) {
76686
76806
  ctx.output.data(matches.map((m) => m.data));
@@ -81226,7 +81346,7 @@ async function runValidateEval(ctx, scenarios, options) {
81226
81346
  return results;
81227
81347
  }
81228
81348
  async function runE2EEval(ctx, scenarios, options) {
81229
- const { runPipeline: runPipeline2 } = await import("./pipeline-FGI6ICWM.js");
81349
+ const { runPipeline: runPipeline2 } = await import("./pipeline-TMFQSA7X.js");
81230
81350
  const concurrency = options.parallel || 1;
81231
81351
  let completed = 0;
81232
81352
  const outputJson = options.outputJson ?? false;
@@ -94707,7 +94827,10 @@ async function listInboxes(ctx, options) {
94707
94827
  const idsOnly = options.idsOnly === true;
94708
94828
  try {
94709
94829
  const front = getFrontClient(ctx);
94710
- const inboxList = await front.inboxes.list();
94830
+ const inboxList = await withSpinner(
94831
+ "Loading inboxes...",
94832
+ () => front.inboxes.list()
94833
+ );
94711
94834
  const inboxes = inboxList._results ?? [];
94712
94835
  if (idsOnly) {
94713
94836
  for (const inbox of inboxes) {
@@ -94771,7 +94894,10 @@ async function listConversations(ctx, inboxNameOrId, options) {
94771
94894
  const idsOnly = options.idsOnly === true;
94772
94895
  try {
94773
94896
  const front = getFrontClient(ctx);
94774
- const inbox = await findInbox(ctx, inboxNameOrId);
94897
+ const inbox = await withSpinner(
94898
+ "Finding inbox...",
94899
+ () => findInbox(ctx, inboxNameOrId)
94900
+ );
94775
94901
  if (!inbox) {
94776
94902
  throw new CLIError({
94777
94903
  userMessage: `Inbox not found: ${inboxNameOrId}`,
@@ -97235,7 +97361,10 @@ async function listEvents(ctx, options) {
97235
97361
  });
97236
97362
  }
97237
97363
  params.limit = limit2;
97238
- const response = await client.listEvents(params);
97364
+ const response = await withSpinner(
97365
+ "Loading events...",
97366
+ () => client.listEvents(params)
97367
+ );
97239
97368
  if (outputJson) {
97240
97369
  ctx.output.data(response.data);
97241
97370
  } else {
@@ -97258,10 +97387,10 @@ async function getEvent(ctx, id, options) {
97258
97387
  const outputJson = options.json === true || ctx.format === "json";
97259
97388
  try {
97260
97389
  const client = new InngestClient({ dev: options.dev });
97261
- const [event, runs] = await Promise.all([
97262
- client.getEvent(id),
97263
- client.getEventRuns(id)
97264
- ]);
97390
+ const [event, runs] = await withSpinner(
97391
+ "Loading event...",
97392
+ () => Promise.all([client.getEvent(id), client.getEventRuns(id)])
97393
+ );
97265
97394
  if (outputJson) {
97266
97395
  ctx.output.data({ event, runs });
97267
97396
  } else {
@@ -97691,7 +97820,7 @@ async function runCommand(ctx, id, options) {
97691
97820
  try {
97692
97821
  const isDev = options.dev ?? await detectDevServer();
97693
97822
  const client = new InngestClient({ dev: isDev });
97694
- const run3 = await client.getRun(id);
97823
+ const run3 = await withSpinner("Loading run...", () => client.getRun(id));
97695
97824
  if (outputJson) {
97696
97825
  ctx.output.data(run3);
97697
97826
  } else {
@@ -114094,6 +114223,133 @@ function registerKeysCommands(program3) {
114094
114223
  }
114095
114224
  }
114096
114225
  });
114226
+ keys.command("setup").description("Set up keychain + shell integration (tries everything)").option("--json", "Output as JSON").action(async (options, command) => {
114227
+ const ctx = await buildContext4(command, options.json);
114228
+ const outputJson = options.json || ctx.format === "json";
114229
+ const OP_VAULT_LINK = "https://start.1password.com/open/i?a=GCTJE4MRGFHKRAYXCEXKZKCEFU&v=u3ujzar6l3nahlahsuzfvg7vcq&i=3e4ip354ps3mhq2wwt6vmtm2zu&h=egghead.1password.com";
114230
+ const status = getKeychainStatus();
114231
+ const steps = [];
114232
+ const errors2 = [];
114233
+ if (status.opTokenInKeychain && status.ageKeyInKeychain && status.shellIntegration) {
114234
+ if (outputJson) {
114235
+ ctx.output.data({ success: true, status: "configured" });
114236
+ } else {
114237
+ ctx.output.data("\u2713 Already configured");
114238
+ }
114239
+ return;
114240
+ }
114241
+ let opToken = null;
114242
+ if (process.env.OP_SERVICE_ACCOUNT_TOKEN) {
114243
+ opToken = process.env.OP_SERVICE_ACCOUNT_TOKEN;
114244
+ steps.push("\u2713 OP token from env");
114245
+ }
114246
+ if (!opToken) {
114247
+ const { getFromKeychain } = await import("./keychain-IEZHT5WN.js");
114248
+ opToken = getFromKeychain("op-service-account-token");
114249
+ if (opToken) steps.push("\u2713 OP token from keychain");
114250
+ }
114251
+ if (!opToken && status.opCliAvailable) {
114252
+ opToken = autoBootstrapKeychain();
114253
+ if (opToken) steps.push("\u2713 OP token from op CLI");
114254
+ }
114255
+ if (opToken && !status.opTokenInKeychain && isKeychainSupported()) {
114256
+ if (storeInKeychain("op-service-account-token", opToken)) {
114257
+ steps.push("\u2713 OP token \u2192 keychain");
114258
+ } else {
114259
+ errors2.push("Could not store OP token in keychain");
114260
+ }
114261
+ }
114262
+ let ageKey = null;
114263
+ if (process.env.SKILL_AGE_KEY) {
114264
+ ageKey = process.env.SKILL_AGE_KEY;
114265
+ steps.push("\u2713 Age key from env");
114266
+ }
114267
+ if (!ageKey) {
114268
+ const { getFromKeychain } = await import("./keychain-IEZHT5WN.js");
114269
+ ageKey = getFromKeychain("age-private-key");
114270
+ if (ageKey) steps.push("\u2713 Age key from keychain");
114271
+ }
114272
+ if (!ageKey && opToken) {
114273
+ const originalEnv = process.env.OP_SERVICE_ACCOUNT_TOKEN;
114274
+ process.env.OP_SERVICE_ACCOUNT_TOKEN = opToken;
114275
+ try {
114276
+ const { OnePasswordProvider: OnePasswordProvider2 } = await import("./secrets-MGVPGMFJ.js");
114277
+ const op = new OnePasswordProvider2();
114278
+ if (await op.isAvailable()) {
114279
+ ageKey = await op.resolve(
114280
+ "op://Support/skill-cli-age-key/private_key"
114281
+ );
114282
+ if (ageKey) steps.push("\u2713 Age key from 1Password");
114283
+ }
114284
+ } catch {
114285
+ errors2.push("1Password SDK failed");
114286
+ } finally {
114287
+ if (originalEnv) {
114288
+ process.env.OP_SERVICE_ACCOUNT_TOKEN = originalEnv;
114289
+ } else {
114290
+ delete process.env.OP_SERVICE_ACCOUNT_TOKEN;
114291
+ }
114292
+ }
114293
+ }
114294
+ if (ageKey && !status.ageKeyInKeychain && isKeychainSupported()) {
114295
+ if (storeInKeychain("age-private-key", ageKey)) {
114296
+ steps.push("\u2713 Age key \u2192 keychain");
114297
+ } else {
114298
+ errors2.push("Could not store age key in keychain");
114299
+ }
114300
+ }
114301
+ if (!status.shellIntegration && isKeychainSupported()) {
114302
+ const r = addShellIntegration();
114303
+ if (r.success) {
114304
+ steps.push(`\u2713 Shell \u2192 ${r.path}`);
114305
+ } else {
114306
+ errors2.push(`Shell integration: ${r.error}`);
114307
+ }
114308
+ }
114309
+ const finalStatus = getKeychainStatus();
114310
+ const success = finalStatus.opTokenInKeychain && finalStatus.ageKeyInKeychain;
114311
+ if (outputJson) {
114312
+ ctx.output.data({ success, steps, errors: errors2, status: finalStatus });
114313
+ return;
114314
+ }
114315
+ for (const s of steps) {
114316
+ ctx.output.data(s);
114317
+ }
114318
+ if (success) {
114319
+ ctx.output.data("");
114320
+ ctx.output.data("\u2713 Done! Run: source ~/.zshrc");
114321
+ return;
114322
+ }
114323
+ ctx.output.data("");
114324
+ ctx.output.data("\u2500".repeat(50));
114325
+ ctx.output.data("Could not complete automatic setup. Manual steps:");
114326
+ ctx.output.data("");
114327
+ if (!opToken) {
114328
+ ctx.output.data("1. Get OP_SERVICE_ACCOUNT_TOKEN:");
114329
+ ctx.output.data(` open "${OP_VAULT_LINK}"`);
114330
+ ctx.output.data(' Copy the "credential" field');
114331
+ ctx.output.data("");
114332
+ ctx.output.data("2. Add to ~/.zshrc:");
114333
+ ctx.output.data(' export OP_SERVICE_ACCOUNT_TOKEN="<paste>"');
114334
+ ctx.output.data("");
114335
+ }
114336
+ if (!ageKey) {
114337
+ ctx.output.data("3. Get age key (requires OP token):");
114338
+ ctx.output.data(
114339
+ ' op read "op://Support/skill-cli-age-key/private_key"'
114340
+ );
114341
+ ctx.output.data("");
114342
+ ctx.output.data("4. Add to ~/.zshrc:");
114343
+ ctx.output.data(' export SKILL_AGE_KEY="<paste>"');
114344
+ ctx.output.data("");
114345
+ }
114346
+ if (!isKeychainSupported()) {
114347
+ ctx.output.data(
114348
+ "Note: No keychain on this platform. Use env vars instead."
114349
+ );
114350
+ }
114351
+ ctx.output.data("Then run: source ~/.zshrc");
114352
+ });
114097
114353
  }
114098
114354
 
114099
114355
  // src/commands/linear/index.ts
@@ -115561,26 +115817,31 @@ async function listMyIssues(ctx, options = {}) {
115561
115817
  const limit2 = options.limit || 20;
115562
115818
  try {
115563
115819
  const client = getLinearClient();
115564
- const viewer = await client.viewer;
115565
- const filter4 = {
115566
- assignee: { id: { eq: viewer.id } },
115567
- state: {
115568
- type: {
115569
- nin: ["canceled", "completed"]
115820
+ const { viewer, issues } = await withSpinner(
115821
+ "Loading issues...",
115822
+ async () => {
115823
+ const viewer2 = await client.viewer;
115824
+ const filter4 = {
115825
+ assignee: { id: { eq: viewer2.id } },
115826
+ state: {
115827
+ type: {
115828
+ nin: ["canceled", "completed"]
115829
+ }
115830
+ }
115831
+ };
115832
+ if (options.state) {
115833
+ filter4.state = {
115834
+ ...filter4.state || {},
115835
+ name: { eqIgnoreCase: options.state }
115836
+ };
115570
115837
  }
115838
+ const response = await client.issues({
115839
+ first: limit2,
115840
+ filter: filter4
115841
+ });
115842
+ return { viewer: viewer2, issues: response.nodes || [] };
115571
115843
  }
115572
- };
115573
- if (options.state) {
115574
- filter4.state = {
115575
- ...filter4.state || {},
115576
- name: { eqIgnoreCase: options.state }
115577
- };
115578
- }
115579
- const response = await client.issues({
115580
- first: limit2,
115581
- filter: filter4
115582
- });
115583
- const issues = response.nodes || [];
115844
+ );
115584
115845
  const issuesWithDetails = await Promise.all(
115585
115846
  issues.map(async (issue) => ({
115586
115847
  issue,
@@ -115759,9 +116020,12 @@ async function searchIssues(ctx, query, options = {}) {
115759
116020
  const limit2 = options.limit || 20;
115760
116021
  try {
115761
116022
  const client = getLinearClient();
115762
- const response = await client.searchIssues(query.trim(), {
115763
- first: limit2
115764
- });
116023
+ const response = await withSpinner(
116024
+ "Searching issues...",
116025
+ () => client.searchIssues(query.trim(), {
116026
+ first: limit2
116027
+ })
116028
+ );
115765
116029
  const issues = response.nodes || [];
115766
116030
  const issuesWithDetails = await Promise.all(
115767
116031
  issues.map(async (issue) => ({
@@ -116050,7 +116314,7 @@ init_esm_shims();
116050
116314
  async function listTeams(ctx, options = {}) {
116051
116315
  try {
116052
116316
  const client = getLinearClient();
116053
- const response = await client.teams();
116317
+ const response = await withSpinner("Loading teams...", () => client.teams());
116054
116318
  const teams = response.nodes || [];
116055
116319
  if (ctx.format === "json") {
116056
116320
  ctx.output.data(
@@ -117604,7 +117868,7 @@ var handlePipelineError = (ctx, error, message, suggestion = "Verify inputs and
117604
117868
  async function runPipelineCommand(ctx, opts) {
117605
117869
  const outputJson = opts.json === true || ctx.format === "json";
117606
117870
  try {
117607
- const { runPipeline: runPipeline2 } = await import("./pipeline-FGI6ICWM.js");
117871
+ const { runPipeline: runPipeline2 } = await import("./pipeline-TMFQSA7X.js");
117608
117872
  const result = await runPipeline2({
117609
117873
  message: {
117610
117874
  subject: opts.subject,
@@ -119220,9 +119484,6 @@ init_esm_shims();
119220
119484
  var DEFAULT_MAX_HINTS = 2;
119221
119485
  var getCommandCount = (state, command) => state.commands[command]?.count ?? 0;
119222
119486
  var hasCommand = (state, command) => getCommandCount(state, command) > 0;
119223
- var hasCommandPrefix = (state, prefix) => Object.entries(state.commands).some(
119224
- ([name, entry]) => name.startsWith(prefix) && entry.count > 0
119225
- );
119226
119487
  var hasMilestone = (state, milestone) => state.milestones[milestone]?.achieved ?? false;
119227
119488
  var shouldSuppressHints = (context) => context.quiet === true || context.format === "json";
119228
119489
  var resolveMaxHints = (context) => context.maxHints ?? DEFAULT_MAX_HINTS;
@@ -119231,79 +119492,76 @@ var toHint = (rule) => ({
119231
119492
  message: rule.message,
119232
119493
  audience: rule.audience
119233
119494
  });
119495
+ var isCommandGroup = (command, group) => command === group || command.startsWith(`${group}.`);
119234
119496
  var DEFAULT_HINT_RULES = [
119497
+ // Front contextual hints
119235
119498
  {
119236
- id: "onboarding.wizard",
119237
- audience: "onboarding",
119238
- message: "New here? Run `skill wizard` to set up your first product.",
119239
- showWhen: (state) => state.totalRuns <= 2 && !hasCommand(state, "wizard"),
119240
- retireWhen: (state) => hasCommand(state, "wizard") || hasMilestone(state, "wizard_completed")
119241
- },
119242
- {
119243
- id: "onboarding.auth",
119244
- audience: "onboarding",
119245
- message: "Set up your own API keys with `skill keys`.",
119246
- showWhen: (state) => state.totalRuns >= 1 && !hasMilestone(state, "auth_configured"),
119247
- retireWhen: (state) => hasMilestone(state, "auth_configured")
119248
- },
119249
- {
119250
- id: "discovery.health",
119251
- audience: "discovery",
119252
- message: "Check integrations fast with `skill health <app-slug>`.",
119253
- showWhen: (state) => state.totalRuns >= 2 && !hasCommand(state, "health"),
119254
- retireWhen: (state) => hasCommand(state, "health")
119499
+ id: "context.front.triage",
119500
+ audience: "contextual",
119501
+ postRun: true,
119502
+ message: "Tip: `skill front triage` to auto-categorize unassigned threads.",
119503
+ showWhen: (state, context) => context.command === "front.inbox" && !hasCommand(state, "front.triage"),
119504
+ retireWhen: (state) => hasCommand(state, "front.triage")
119255
119505
  },
119256
119506
  {
119257
- id: "discovery.front.inbox",
119258
- audience: "discovery",
119259
- message: "List recent conversations via `skill front inbox <name-or-id>`.",
119260
- showWhen: (state) => state.totalRuns >= 1 && !hasCommand(state, "front.inbox"),
119261
- retireWhen: (state) => hasCommand(state, "front.inbox")
119507
+ id: "context.front.conversation",
119508
+ audience: "contextual",
119509
+ postRun: true,
119510
+ message: "Tip: `skill front conversation <id> -m` shows the full thread.",
119511
+ showWhen: (state, context) => context.command === "front.message" && !hasCommand(state, "front.conversation"),
119512
+ retireWhen: (state) => hasCommand(state, "front.conversation")
119262
119513
  },
119263
119514
  {
119264
- id: "discovery.inngest",
119265
- audience: "discovery",
119266
- message: "Inspect workflows with `skill inngest stats --after 1d`.",
119267
- showWhen: (state) => state.totalRuns >= 3 && !hasCommandPrefix(state, "inngest."),
119268
- retireWhen: (state) => hasCommandPrefix(state, "inngest.")
119515
+ id: "context.front.reply",
119516
+ audience: "contextual",
119517
+ postRun: true,
119518
+ message: "Tip: `skill front reply <id>` to draft a response.",
119519
+ showWhen: (state, context) => context.command === "front.conversation" && !hasCommand(state, "front.reply"),
119520
+ retireWhen: (state) => hasCommand(state, "front.reply")
119269
119521
  },
119522
+ // Inngest contextual hints
119270
119523
  {
119271
- id: "discovery.axiom",
119272
- audience: "discovery",
119273
- message: 'Query logs quickly with `skill axiom query "<APL>" --since 24h`.',
119274
- showWhen: (state) => state.totalRuns >= 3 && !hasCommandPrefix(state, "axiom."),
119275
- retireWhen: (state) => hasCommandPrefix(state, "axiom.")
119524
+ id: "context.inngest.run",
119525
+ audience: "contextual",
119526
+ postRun: true,
119527
+ message: "Tip: `skill inngest run <id>` to inspect a specific run.",
119528
+ showWhen: (state, context) => (context.command === "inngest.failures" || context.command === "inngest.runs") && !hasCommand(state, "inngest.run"),
119529
+ retireWhen: (state) => hasCommand(state, "inngest.run")
119276
119530
  },
119277
119531
  {
119278
- id: "discovery.keys",
119279
- audience: "discovery",
119280
- message: "Override shared credentials with your own: `skill keys add`",
119281
- showWhen: (state) => state.totalRuns >= 3 && !hasCommand(state, "keys") && !hasMilestone(state, "auth_configured"),
119282
- retireWhen: (state) => hasCommand(state, "keys") || hasCommand(state, "keys.add") || hasMilestone(state, "auth_configured")
119532
+ id: "context.inngest.trace",
119533
+ audience: "contextual",
119534
+ postRun: true,
119535
+ message: "Tip: `skill inngest trace <run-id>` for full workflow trace.",
119536
+ showWhen: (state, context) => context.command === "inngest.run" && !hasCommand(state, "inngest.trace"),
119537
+ retireWhen: (state) => hasCommand(state, "inngest.trace")
119283
119538
  },
119539
+ // Linear contextual hints
119284
119540
  {
119285
- id: "context.front.triage",
119541
+ id: "context.linear.my",
119286
119542
  audience: "contextual",
119287
119543
  postRun: true,
119288
- message: "Tip: `skill front triage <inbox-id>` surfaces unassigned threads.",
119289
- showWhen: (state, context) => context.command === "front.inbox" && !hasCommand(state, "front.triage"),
119290
- retireWhen: (state) => hasCommand(state, "front.triage")
119544
+ message: "Tip: `skill linear my` to see your assigned issues.",
119545
+ showWhen: (state, context) => isCommandGroup(context.command, "linear") && context.command !== "linear.my" && !hasCommand(state, "linear.my"),
119546
+ retireWhen: (state) => hasCommand(state, "linear.my")
119291
119547
  },
119548
+ // Axiom contextual hints
119292
119549
  {
119293
- id: "context.front.conversation",
119550
+ id: "context.axiom.errors",
119294
119551
  audience: "contextual",
119295
119552
  postRun: true,
119296
- message: "Tip: `skill front conversation <id> -m` shows the full thread.",
119297
- showWhen: (state, context) => context.command === "front.message" && !hasCommand(state, "front.conversation"),
119298
- retireWhen: (state) => hasCommand(state, "front.conversation")
119553
+ message: "Tip: `skill axiom errors --since 1h` to see recent errors.",
119554
+ showWhen: (state, context) => context.command === "axiom.query" && !hasCommand(state, "axiom.errors"),
119555
+ retireWhen: (state) => hasCommand(state, "axiom.errors")
119299
119556
  },
119557
+ // Keys hint - only when auth issues are likely
119300
119558
  {
119301
- id: "context.inngest.run",
119559
+ id: "context.keys",
119302
119560
  audience: "contextual",
119303
119561
  postRun: true,
119304
- message: "Tip: drill in with `skill inngest run <id>` or `skill inngest trace <run-id>`.",
119305
- showWhen: (state, context) => context.command === "inngest.failures" && !hasCommand(state, "inngest.run") && !hasCommand(state, "inngest.trace"),
119306
- retireWhen: (state) => hasCommand(state, "inngest.run") || hasCommand(state, "inngest.trace")
119562
+ message: "Tip: `skill keys setup` to configure keychain integration.",
119563
+ showWhen: (state, context) => context.command === "auth.status" && !hasCommand(state, "keys.setup") && !hasMilestone(state, "auth_configured"),
119564
+ retireWhen: (state) => hasCommand(state, "keys.setup") || hasMilestone(state, "auth_configured")
119307
119565
  }
119308
119566
  ];
119309
119567
  var HintEngine = class {
@@ -120087,8 +120345,8 @@ if (!envLoaded && !process.env.DATABASE_URL) {
120087
120345
  process.env.SKIP_ENV_VALIDATION = "1";
120088
120346
  }
120089
120347
  var runtimeTarget = `bun-${process.platform}-${process.arch}`;
120090
- var buildVersion = "0.16.1".length > 0 ? "0.16.1" : "0.0.0-dev";
120091
- var buildCommit = "7f0ef62".length > 0 ? "7f0ef62" : "dev";
120348
+ var buildVersion = "0.17.0".length > 0 ? "0.17.0" : "0.0.0-dev";
120349
+ var buildCommit = "e664abd".length > 0 ? "e664abd" : "dev";
120092
120350
  var buildTarget = "node".length > 0 ? "node" : runtimeTarget;
120093
120351
  var isDevBuild = buildVersion.includes("dev") || buildCommit === "dev";
120094
120352
  var versionLabel = `skill v${buildVersion} (${buildCommit}) ${buildTarget}`;
@@ -120102,7 +120360,6 @@ var usageState = await (async () => {
120102
120360
  return null;
120103
120361
  }
120104
120362
  })();
120105
- var hintCounts = /* @__PURE__ */ new WeakMap();
120106
120363
  var commandStartTimes = /* @__PURE__ */ new WeakMap();
120107
120364
  var resolveCommandName = (command) => {
120108
120365
  const names = [];
@@ -120158,16 +120415,6 @@ program2.hook("preAction", (thisCommand, actionCommand) => {
120158
120415
  program2.hook("preAction", (_thisCommand, actionCommand) => {
120159
120416
  commandStartTimes.set(actionCommand, Date.now());
120160
120417
  });
120161
- program2.hook("preAction", async (_thisCommand, actionCommand) => {
120162
- try {
120163
- const context = resolveHintContext(actionCommand);
120164
- const state = await usageTracker.getUsage();
120165
- const hints = hintEngine.getHints(state, context);
120166
- writeHints(hints, process.stderr);
120167
- hintCounts.set(actionCommand, hints.length);
120168
- } catch {
120169
- }
120170
- });
120171
120418
  program2.hook("postAction", async (_thisCommand, actionCommand) => {
120172
120419
  try {
120173
120420
  const context = resolveHintContext(actionCommand);
@@ -120176,11 +120423,7 @@ program2.hook("postAction", async (_thisCommand, actionCommand) => {
120176
120423
  for (const milestone of milestones) {
120177
120424
  await usageTracker.setMilestone(milestone);
120178
120425
  }
120179
- const previouslyShown = hintCounts.get(actionCommand) ?? 0;
120180
- const postHint = hintEngine.getPostRunHint(state, {
120181
- ...context,
120182
- previouslyShown
120183
- });
120426
+ const postHint = hintEngine.getPostRunHint(state, context);
120184
120427
  if (postHint) writeHints([postHint], process.stderr);
120185
120428
  } catch {
120186
120429
  }