@wave-ai-os/wave-cli 0.1.59 → 0.1.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 (3) hide show
  1. package/dist/index.cjs +261 -213
  2. package/dist/index.js +261 -213
  3. package/package.json +1 -1
package/dist/index.cjs CHANGED
@@ -666,7 +666,7 @@ async function requestGraphqlHttp(params) {
666
666
  Authorization: `Bearer ${params.input.config.token}`,
667
667
  Accept: "application/json",
668
668
  "Content-Type": "application/json",
669
- "X-Origin": "langgraph-cli",
669
+ "X-Origin": "wave-cli",
670
670
  "X-Request-Id": params.requestId,
671
671
  ...params.input.config.agentName ? { "X-Agent-Name": params.input.config.agentName } : {},
672
672
  ...params.input.config.agentRunId ? { "X-Agent-Run-Id": params.input.config.agentRunId } : {}
@@ -2137,13 +2137,18 @@ function resolveFromSources(options, stdin, config, env) {
2137
2137
  normalize3(env.WAVE_API_URL),
2138
2138
  normalize3(config.baseUrl)
2139
2139
  );
2140
- const organizationId = firstDefined(
2141
- normalize3(options.organizationId),
2142
- normalize3(stdin.organizationId),
2143
- normalize3(env.WAVE_ORGANIZATION_ID),
2144
- normalize3(env.WAVE_ORG_ID),
2145
- normalize3(config.organizationId)
2146
- );
2140
+ const organizationCandidates = [
2141
+ { organizationId: normalize3(options.organizationId), source: "flag" },
2142
+ { organizationId: normalize3(stdin.organizationId), source: "stdin" },
2143
+ { organizationId: normalize3(env.WAVE_ORGANIZATION_ID), source: "env" },
2144
+ { organizationId: normalize3(env.WAVE_ORG_ID), source: "env" },
2145
+ { organizationId: normalize3(config.organizationId), source: "config" }
2146
+ ];
2147
+ const resolvedOrganization = organizationCandidates.find((candidate) => candidate.organizationId) ?? {
2148
+ organizationId: void 0,
2149
+ source: "none"
2150
+ };
2151
+ const organizationId = resolvedOrganization.organizationId;
2147
2152
  const timeoutMs = firstDefined(options.timeoutMs, stdin.timeoutMs, env.WAVE_TIMEOUT_MS, config.timeoutMs);
2148
2153
  const debug = firstDefined(
2149
2154
  options.debug,
@@ -2232,6 +2237,7 @@ function resolveFromSources(options, stdin, config, env) {
2232
2237
  const resolvedAuth = resolveAuthToken(options, stdin, config, env);
2233
2238
  return {
2234
2239
  organizationId,
2240
+ organizationIdSource: resolvedOrganization.source,
2235
2241
  runtimeOptions: {
2236
2242
  token: resolvedAuth.token,
2237
2243
  tokenSource: resolvedAuth.token ? resolvedAuth.source : "none",
@@ -2441,6 +2447,140 @@ function registerGraphqlSearchCommand(command, config) {
2441
2447
  });
2442
2448
  }
2443
2449
 
2450
+ // src/authClient.ts
2451
+ var import_node_crypto2 = require("crypto");
2452
+
2453
+ // src/redaction.ts
2454
+ var TOKENISH_PATTERNS = [
2455
+ /\b(?:cli|wave|token|secret|bearer)[A-Za-z0-9._~+/=-]{8,}\b/gi,
2456
+ /\b[A-Za-z0-9._~+/=-]{24,}\b/g
2457
+ ];
2458
+ function redactOne(value) {
2459
+ if (value.length <= 8) {
2460
+ return "[redacted]";
2461
+ }
2462
+ return `${value.slice(0, 4)}...[redacted]...${value.slice(-4)}`;
2463
+ }
2464
+ function redactSecrets(input, knownSecrets = []) {
2465
+ let output = input;
2466
+ for (const secret of knownSecrets) {
2467
+ if (!secret) continue;
2468
+ output = output.split(secret).join(redactOne(secret));
2469
+ }
2470
+ for (const pattern of TOKENISH_PATTERNS) {
2471
+ output = output.replace(pattern, (match) => redactOne(match));
2472
+ }
2473
+ return output;
2474
+ }
2475
+ function redactUnknown(input, knownSecrets = []) {
2476
+ if (typeof input === "string") {
2477
+ return redactSecrets(input, knownSecrets);
2478
+ }
2479
+ if (Array.isArray(input)) {
2480
+ return input.map((entry2) => redactUnknown(entry2, knownSecrets));
2481
+ }
2482
+ if (!input || typeof input !== "object") {
2483
+ return input;
2484
+ }
2485
+ const output = {};
2486
+ for (const [key, value] of Object.entries(input)) {
2487
+ if (/token|secret|authorization|bearer/i.test(key)) {
2488
+ output[key] = typeof value === "string" ? redactSecrets(value, knownSecrets) : "[redacted]";
2489
+ continue;
2490
+ }
2491
+ output[key] = redactUnknown(value, knownSecrets);
2492
+ }
2493
+ return output;
2494
+ }
2495
+
2496
+ // src/authClient.ts
2497
+ function parseJsonSafely2(input) {
2498
+ try {
2499
+ return JSON.parse(input);
2500
+ } catch {
2501
+ return null;
2502
+ }
2503
+ }
2504
+ function graphqlErrors(payload, knownSecrets) {
2505
+ const errors = payload.errors;
2506
+ if (!Array.isArray(errors) || errors.length === 0) return null;
2507
+ return {
2508
+ code: "upstream_error",
2509
+ message: "GraphQL request failed.",
2510
+ status: 400,
2511
+ details: {
2512
+ errors: redactUnknown(errors, knownSecrets)
2513
+ }
2514
+ };
2515
+ }
2516
+ async function authGraphqlRequest(params) {
2517
+ const requestId = (0, import_node_crypto2.randomUUID)();
2518
+ const controller = new AbortController();
2519
+ const timeoutId = setTimeout(() => controller.abort(), params.timeoutMs);
2520
+ const knownSecrets = [params.token, ...params.knownSecrets ?? []].filter(
2521
+ (secret) => typeof secret === "string" && secret.length > 0
2522
+ );
2523
+ try {
2524
+ const url = new URL("/graphql", params.baseUrl);
2525
+ const response = await fetch(url, {
2526
+ method: "POST",
2527
+ headers: {
2528
+ Accept: "application/json",
2529
+ "Content-Type": "application/json",
2530
+ "X-Origin": "wave-cli",
2531
+ "X-Request-Id": requestId,
2532
+ ...params.token ? { Authorization: `Bearer ${params.token}` } : {}
2533
+ },
2534
+ body: JSON.stringify({ query: params.query, variables: params.variables ?? {} }),
2535
+ signal: controller.signal
2536
+ });
2537
+ const responseRequestId = response.headers.get("x-request-id") ?? requestId;
2538
+ const text = await response.text();
2539
+ const payload = text ? parseJsonSafely2(text) : null;
2540
+ const graph = payload && typeof payload === "object" && !Array.isArray(payload) ? payload : {};
2541
+ const gqlError = graphqlErrors(graph, knownSecrets);
2542
+ if (gqlError) {
2543
+ return { ok: false, error: gqlError, requestId: responseRequestId };
2544
+ }
2545
+ if (!response.ok) {
2546
+ return {
2547
+ ok: false,
2548
+ requestId: responseRequestId,
2549
+ error: {
2550
+ code: `http_${response.status}`,
2551
+ message: "Auth request failed.",
2552
+ status: response.status,
2553
+ details: { body: redactUnknown(graph, knownSecrets) }
2554
+ }
2555
+ };
2556
+ }
2557
+ const data = graph.data && typeof graph.data === "object" && !Array.isArray(graph.data) ? graph.data : {};
2558
+ return {
2559
+ ok: true,
2560
+ result: {
2561
+ status: response.status,
2562
+ requestId: responseRequestId,
2563
+ data
2564
+ }
2565
+ };
2566
+ } catch (error) {
2567
+ const message = error instanceof Error ? error.message : "Network error.";
2568
+ const timedOut = error instanceof Error && error.name === "AbortError";
2569
+ return {
2570
+ ok: false,
2571
+ requestId,
2572
+ error: {
2573
+ code: timedOut ? "timeout" : "network_error",
2574
+ message: redactSecrets(timedOut ? "Auth request timed out." : message, knownSecrets),
2575
+ status: timedOut ? 408 : 503,
2576
+ details: {}
2577
+ }
2578
+ };
2579
+ } finally {
2580
+ clearTimeout(timeoutId);
2581
+ }
2582
+ }
2583
+
2444
2584
  // src/commands/tasks.ts
2445
2585
  var projectIdSchema = import_zod2.z.string().min(1);
2446
2586
  var idSchema = import_zod2.z.string().min(1);
@@ -2469,6 +2609,44 @@ function parseTaskUpdateJson(raw) {
2469
2609
  function parseLabelIds(raw) {
2470
2610
  return raw.split(",").map((labelId) => labelId.trim()).filter((labelId) => labelId.length > 0);
2471
2611
  }
2612
+ function asRecord3(value) {
2613
+ if (!value || typeof value !== "object" || Array.isArray(value)) {
2614
+ return null;
2615
+ }
2616
+ return value;
2617
+ }
2618
+ function asNonEmptyString2(value) {
2619
+ if (typeof value !== "string") {
2620
+ return void 0;
2621
+ }
2622
+ const trimmed = value.trim();
2623
+ return trimmed.length > 0 ? trimmed : void 0;
2624
+ }
2625
+ async function resolveTaskReadOrganizationId(params) {
2626
+ const resolvedOrganizationId = asNonEmptyString2(params.organizationId);
2627
+ if (params.organizationIdSource === "flag" && resolvedOrganizationId) {
2628
+ return resolvedOrganizationId;
2629
+ }
2630
+ const baseUrl = asNonEmptyString2(params.runtimeOptions.baseUrl);
2631
+ const token = asNonEmptyString2(params.runtimeOptions.token);
2632
+ if (baseUrl && token) {
2633
+ const result = await authGraphqlRequest({
2634
+ baseUrl,
2635
+ token,
2636
+ timeoutMs: typeof params.runtimeOptions.timeoutMs === "number" ? params.runtimeOptions.timeoutMs : 1e4,
2637
+ query: "query WaveCliTaskReadOrganization { cliAuthStatus { authenticated baseAuthStatus organization { id slug } } }"
2638
+ });
2639
+ if (result.ok) {
2640
+ const status = asRecord3(result.result.data.cliAuthStatus);
2641
+ const organization = status ? asRecord3(status.organization) : null;
2642
+ const organizationId = organization ? asNonEmptyString2(organization.id) : void 0;
2643
+ if (organizationId) {
2644
+ return organizationId;
2645
+ }
2646
+ }
2647
+ }
2648
+ return resolveOrganizationId(resolvedOrganizationId);
2649
+ }
2472
2650
  function registerTaskCommands(program) {
2473
2651
  const tasks = program.command("tasks").description("Task operations");
2474
2652
  tasks.command("list").option("--project-id <projectId>").option("--page <page>").option("--per <per>").option("--team-id <teamId>").option("--team-ids <teamIds>").option("--member-id <memberId>").option("--meeting-id <meetingId>").option("--field-name <fieldName>").option("--field-value <fieldValue>").option("--field-blank <fieldBlank>").option("--open <open>").option("--rank-direction <rankDirection>").option("--include-archived <includeArchived>").action(async (opts, cmd) => {
@@ -2505,7 +2683,11 @@ function registerTaskCommands(program) {
2505
2683
  tasks.command("show").requiredOption("--id <id>").action(async (opts, cmd) => {
2506
2684
  const parsed = idSchema.parse(opts.id);
2507
2685
  const context = await resolveCommandContext(cmd.optsWithGlobals());
2508
- const organizationId = resolveOrganizationId(context.organizationId);
2686
+ const organizationId = await resolveTaskReadOrganizationId({
2687
+ organizationId: context.organizationId,
2688
+ organizationIdSource: context.organizationIdSource,
2689
+ runtimeOptions: context.runtimeOptions
2690
+ });
2509
2691
  await runGraphqlQueryCommand({
2510
2692
  command: "tasks.show",
2511
2693
  runtimeOptions: context.runtimeOptions,
@@ -3407,16 +3589,16 @@ var displayPreferenceAttributesSelectionSet = "attributes { id viewType favorite
3407
3589
  var filterPreferenceAttributesSelectionSet = "attributes { id filterType filter memberId focusMemberId focusTeamId filterableId filterableType preferenceType agendaItemId }";
3408
3590
  var healthUpdateSummarySelectionSet = "id type value memberId status createdAt updatedAt updatableType updatableId parentUpdateId emojis { id name memberId } resources { ...ResourceSummaryFull }";
3409
3591
  var projectShowFullSelectionSet = `{ id type name slug description status priority createdAt updatedAt startDate targetDate archivedAt memberId organizationId teamIds emoji { id name memberId } backgroundImage { backgroundType gradientStart gradientEnd gradientDegrees color imageUrl image { url lowUrl } } favorites { id memberId } resources { ...ResourceSummaryFull } displayPreference { id type ${displayPreferenceAttributesSelectionSet} viewType favorite groupingField groupToggleState memberId focusMemberId focusTeamId displayableId displayableType preferenceType agendaItemId } filterPreferences { id type ${filterPreferenceAttributesSelectionSet} filterType filter memberId focusMemberId focusTeamId filterableId filterableType preferenceType agendaItemId } healthUpdates { ${healthUpdateSummarySelectionSet} replies { ${healthUpdateSummarySelectionSet} replies { id type } } } } fragment ResourceSummaryFull on ResourceSummary { id resourceType slug url skillId skill { id name slug emoji scope description } metadata { urlName imageUrl siteName providerName mediaType skillId skillName skillSlug skillScope skillEmoji skillDescription } attachment { id fileKey filename url } content { id name slug type firstChildSlug childCount } }`;
3410
- function asRecord3(value) {
3592
+ function asRecord4(value) {
3411
3593
  return value && typeof value === "object" ? value : null;
3412
3594
  }
3413
3595
  function toNonEmptyString(value) {
3414
3596
  return typeof value === "string" && value.trim() !== "" ? value : void 0;
3415
3597
  }
3416
3598
  function normalizeProjectRowForDisplay(row) {
3417
- const record = asRecord3(row);
3599
+ const record = asRecord4(row);
3418
3600
  if (!record) return row;
3419
- const attributes = asRecord3(record.attributes);
3601
+ const attributes = asRecord4(record.attributes);
3420
3602
  const topLevelName = toNonEmptyString(record.name);
3421
3603
  const topLevelTitle = toNonEmptyString(record.title);
3422
3604
  const attributeName = toNonEmptyString(attributes?.name);
@@ -3431,7 +3613,7 @@ function normalizeProjectRowForDisplay(row) {
3431
3613
  };
3432
3614
  }
3433
3615
  function normalizeProjectsListForDisplay(payload) {
3434
- const record = asRecord3(payload);
3616
+ const record = asRecord4(payload);
3435
3617
  if (!record || !Array.isArray(record.data)) return payload;
3436
3618
  return {
3437
3619
  ...record,
@@ -3639,7 +3821,7 @@ var MEETING_STATUSES = /* @__PURE__ */ new Set(["upcoming", "active", "completed
3639
3821
  var MEETING_REPEATS = /* @__PURE__ */ new Set(["never", "weekly", "biweekly", "monthly", "quarterly"]);
3640
3822
  var createHelp2 = buildDataJsonHelp("meeting", "create") ?? 'JSON object for meeting or {"meeting": {...}}';
3641
3823
  var updateHelp2 = buildDataJsonHelp("meeting", "update") ?? 'JSON object for meeting or {"meeting": {...}}';
3642
- function asNonEmptyString2(value) {
3824
+ function asNonEmptyString3(value) {
3643
3825
  if (typeof value !== "string") {
3644
3826
  return void 0;
3645
3827
  }
@@ -3697,7 +3879,7 @@ function normalizeMeetingCreateBody(body) {
3697
3879
  });
3698
3880
  }
3699
3881
  const meeting = { ...entity };
3700
- const type = asNonEmptyString2(meeting.type);
3882
+ const type = asNonEmptyString3(meeting.type);
3701
3883
  if (!type || !MEETING_TYPES.has(type)) {
3702
3884
  throw new CliError({
3703
3885
  message: "Invalid meeting.type. Use one of: TeamMeeting, OneOnOneMeeting.",
@@ -3707,8 +3889,8 @@ function normalizeMeetingCreateBody(body) {
3707
3889
  details: { field: "meeting.type", allowed: Array.from(MEETING_TYPES) }
3708
3890
  });
3709
3891
  }
3710
- const memberId = asNonEmptyString2(meeting.member_id);
3711
- const date = asNonEmptyString2(meeting.date);
3892
+ const memberId = asNonEmptyString3(meeting.member_id);
3893
+ const date = asNonEmptyString3(meeting.date);
3712
3894
  const startTime = toFiniteNumber(meeting.start_time, "meeting.start_time");
3713
3895
  const missingRequired = [];
3714
3896
  if (!memberId) missingRequired.push("member_id");
@@ -3723,7 +3905,7 @@ function normalizeMeetingCreateBody(body) {
3723
3905
  details: { requiredFields: ["member_id", "date", "start_time"], rootKey: "meeting" }
3724
3906
  });
3725
3907
  }
3726
- const status = asNonEmptyString2(meeting.status);
3908
+ const status = asNonEmptyString3(meeting.status);
3727
3909
  if (status && !MEETING_STATUSES.has(status)) {
3728
3910
  throw new CliError({
3729
3911
  message: "Invalid meeting.status. Use one of: upcoming, active, completed.",
@@ -3733,7 +3915,7 @@ function normalizeMeetingCreateBody(body) {
3733
3915
  details: { field: "meeting.status", allowed: Array.from(MEETING_STATUSES) }
3734
3916
  });
3735
3917
  }
3736
- const repeats = asNonEmptyString2(meeting.repeats) ?? "never";
3918
+ const repeats = asNonEmptyString3(meeting.repeats) ?? "never";
3737
3919
  if (!MEETING_REPEATS.has(repeats)) {
3738
3920
  throw new CliError({
3739
3921
  message: "Invalid meeting.repeats. Use one of: never, weekly, biweekly, monthly, quarterly.",
@@ -4022,7 +4204,7 @@ var SKILL_SELECTION = `{
4022
4204
  createdAt
4023
4205
  updatedAt
4024
4206
  }`;
4025
- function asRecord4(value) {
4207
+ function asRecord5(value) {
4026
4208
  return value && typeof value === "object" && !Array.isArray(value) ? value : null;
4027
4209
  }
4028
4210
  function findSkillById(id) {
@@ -4030,7 +4212,7 @@ function findSkillById(id) {
4030
4212
  if (!Array.isArray(payload)) {
4031
4213
  return null;
4032
4214
  }
4033
- return payload.find((entry2) => String(asRecord4(entry2)?.id ?? "") === id) ?? null;
4215
+ return payload.find((entry2) => String(asRecord5(entry2)?.id ?? "") === id) ?? null;
4034
4216
  };
4035
4217
  }
4036
4218
  function registerSkillCommands(program) {
@@ -4422,7 +4604,7 @@ function normalizeTodosCreateBody(body) {
4422
4604
  }
4423
4605
  return { ...body, todo };
4424
4606
  }
4425
- function asNonEmptyString3(value) {
4607
+ function asNonEmptyString4(value) {
4426
4608
  if (typeof value !== "string") {
4427
4609
  return void 0;
4428
4610
  }
@@ -4430,7 +4612,7 @@ function asNonEmptyString3(value) {
4430
4612
  return trimmed.length > 0 ? trimmed : void 0;
4431
4613
  }
4432
4614
  function validateEnumField(params) {
4433
- const value = asNonEmptyString3(params.rawValue);
4615
+ const value = asNonEmptyString4(params.rawValue);
4434
4616
  if (!value) {
4435
4617
  return void 0;
4436
4618
  }
@@ -4464,7 +4646,7 @@ function normalizeKnowledgeCreateBody(body) {
4464
4646
  message: "Invalid content.status. Use one of: draft, published."
4465
4647
  });
4466
4648
  content.status = status ?? "draft";
4467
- const memberId = asNonEmptyString3(content.member_id);
4649
+ const memberId = asNonEmptyString4(content.member_id);
4468
4650
  if (!memberId) {
4469
4651
  throwMissingRequiredCreateFields("content", ["member_id"]);
4470
4652
  }
@@ -4473,7 +4655,7 @@ function normalizeKnowledgeCreateBody(body) {
4473
4655
  }
4474
4656
  function normalizeNewsCreateBody(body) {
4475
4657
  const headline = ensureEntityObject(body, "headline");
4476
- const memberId = asNonEmptyString3(headline.member_id);
4658
+ const memberId = asNonEmptyString4(headline.member_id);
4477
4659
  if (!memberId) {
4478
4660
  throwMissingRequiredCreateFields("headline", ["member_id"]);
4479
4661
  }
@@ -4502,14 +4684,14 @@ function normalizeNewsCreateBody(body) {
4502
4684
  }
4503
4685
  function normalizeQuestionsCreateBody(body) {
4504
4686
  const question = ensureEntityObject(body, "question");
4505
- const summary = asNonEmptyString3(question.summary);
4506
- const currentName = asNonEmptyString3(question.name);
4687
+ const summary = asNonEmptyString4(question.summary);
4688
+ const currentName = asNonEmptyString4(question.name);
4507
4689
  if (!currentName && summary) {
4508
4690
  question.name = summary;
4509
4691
  }
4510
4692
  delete question.summary;
4511
- const name = asNonEmptyString3(question.name);
4512
- const memberId = asNonEmptyString3(question.member_id);
4693
+ const name = asNonEmptyString4(question.name);
4694
+ const memberId = asNonEmptyString4(question.member_id);
4513
4695
  const missing = [];
4514
4696
  if (!name) missing.push("name");
4515
4697
  if (!memberId) missing.push("member_id");
@@ -4531,13 +4713,13 @@ function normalizeQuestionsCreateBody(body) {
4531
4713
  }
4532
4714
  function normalizeQuestionsUpdateBody(body) {
4533
4715
  const question = ensureEntityObject(body, "question");
4534
- const summary = asNonEmptyString3(question.summary);
4535
- const currentName = asNonEmptyString3(question.name);
4716
+ const summary = asNonEmptyString4(question.summary);
4717
+ const currentName = asNonEmptyString4(question.name);
4536
4718
  if (!currentName && summary) {
4537
4719
  question.name = summary;
4538
4720
  }
4539
4721
  delete question.summary;
4540
- const name = asNonEmptyString3(question.name);
4722
+ const name = asNonEmptyString4(question.name);
4541
4723
  if (name) {
4542
4724
  question.name = name;
4543
4725
  }
@@ -4554,9 +4736,9 @@ function normalizeQuestionsUpdateBody(body) {
4554
4736
  }
4555
4737
  function normalizePulseCreateBody(body) {
4556
4738
  const healthUpdate = ensureEntityObject(body, "health_update");
4557
- const healthUpdatableId = asNonEmptyString3(healthUpdate.health_updatable_id) ?? asNonEmptyString3(healthUpdate.updatable_id);
4558
- const healthUpdatableType = asNonEmptyString3(healthUpdate.health_updatable_type) ?? asNonEmptyString3(healthUpdate.updatable_type);
4559
- const memberId = asNonEmptyString3(healthUpdate.member_id);
4739
+ const healthUpdatableId = asNonEmptyString4(healthUpdate.health_updatable_id) ?? asNonEmptyString4(healthUpdate.updatable_id);
4740
+ const healthUpdatableType = asNonEmptyString4(healthUpdate.health_updatable_type) ?? asNonEmptyString4(healthUpdate.updatable_type);
4741
+ const memberId = asNonEmptyString4(healthUpdate.member_id);
4560
4742
  const status = validateEnumField({
4561
4743
  rawValue: healthUpdate.status,
4562
4744
  field: "health_update.status",
@@ -4581,8 +4763,8 @@ function normalizePulseCreateBody(body) {
4581
4763
  }
4582
4764
  function normalizeSurveysCreateBody(body) {
4583
4765
  const survey = ensureEntityObject(body, "survey");
4584
- const title = asNonEmptyString3(survey.title);
4585
- const currentName = asNonEmptyString3(survey.name);
4766
+ const title = asNonEmptyString4(survey.title);
4767
+ const currentName = asNonEmptyString4(survey.name);
4586
4768
  if (!currentName && title) {
4587
4769
  survey.name = title;
4588
4770
  }
@@ -4611,8 +4793,8 @@ function normalizeSurveysCreateBody(body) {
4611
4793
  }
4612
4794
  function normalizeSurveysUpdateBody(body) {
4613
4795
  const survey = ensureEntityObject(body, "survey");
4614
- const title = asNonEmptyString3(survey.title);
4615
- const currentName = asNonEmptyString3(survey.name);
4796
+ const title = asNonEmptyString4(survey.title);
4797
+ const currentName = asNonEmptyString4(survey.name);
4616
4798
  if (!currentName && title) {
4617
4799
  survey.name = title;
4618
4800
  }
@@ -4639,8 +4821,8 @@ function normalizeSurveysUpdateBody(body) {
4639
4821
  }
4640
4822
  function normalizeFeedbacksCreateBody(body) {
4641
4823
  const feedback = ensureEntityObject(body, "feedback");
4642
- const title = asNonEmptyString3(feedback.title);
4643
- const currentName = asNonEmptyString3(feedback.name);
4824
+ const title = asNonEmptyString4(feedback.title);
4825
+ const currentName = asNonEmptyString4(feedback.name);
4644
4826
  if (!currentName && title) {
4645
4827
  feedback.name = title;
4646
4828
  }
@@ -4657,7 +4839,7 @@ function normalizeFeedbacksCreateBody(body) {
4657
4839
  allowed: FEEDBACK_QUARTERS,
4658
4840
  message: "Invalid feedback.quarter. Use one of: q1, q2, q3, q4."
4659
4841
  });
4660
- const year = asNonEmptyString3(feedback.year);
4842
+ const year = asNonEmptyString4(feedback.year);
4661
4843
  const missing = [];
4662
4844
  if (!name) missing.push("name");
4663
4845
  if (!quarter) missing.push("quarter");
@@ -4672,8 +4854,8 @@ function normalizeFeedbacksCreateBody(body) {
4672
4854
  }
4673
4855
  function normalizeFeedbacksUpdateBody(body) {
4674
4856
  const feedback = ensureEntityObject(body, "feedback");
4675
- const title = asNonEmptyString3(feedback.title);
4676
- const currentName = asNonEmptyString3(feedback.name);
4857
+ const title = asNonEmptyString4(feedback.title);
4858
+ const currentName = asNonEmptyString4(feedback.name);
4677
4859
  if (!currentName && title) {
4678
4860
  feedback.name = title;
4679
4861
  }
@@ -4700,14 +4882,14 @@ function normalizeFeedbacksUpdateBody(body) {
4700
4882
  }
4701
4883
  function normalizeAccountabilityCreateBody(body) {
4702
4884
  const responsibility = ensureEntityObject(body, "responsibility");
4703
- const summary = asNonEmptyString3(responsibility.summary);
4704
- const currentName = asNonEmptyString3(responsibility.name);
4885
+ const summary = asNonEmptyString4(responsibility.summary);
4886
+ const currentName = asNonEmptyString4(responsibility.name);
4705
4887
  if (!currentName && summary) {
4706
4888
  responsibility.name = summary;
4707
4889
  }
4708
4890
  delete responsibility.summary;
4709
- const name = asNonEmptyString3(responsibility.name);
4710
- const memberId = asNonEmptyString3(responsibility.member_id);
4891
+ const name = asNonEmptyString4(responsibility.name);
4892
+ const memberId = asNonEmptyString4(responsibility.member_id);
4711
4893
  const missing = [];
4712
4894
  if (!name) missing.push("name");
4713
4895
  if (!memberId) missing.push("member_id");
@@ -4722,8 +4904,8 @@ function normalizeAccountabilityCreateBody(body) {
4722
4904
  }
4723
4905
  function normalizeAccountabilityUpdateBody(body) {
4724
4906
  const responsibility = ensureEntityObject(body, "responsibility");
4725
- const summary = asNonEmptyString3(responsibility.summary);
4726
- const currentName = asNonEmptyString3(responsibility.name);
4907
+ const summary = asNonEmptyString4(responsibility.summary);
4908
+ const currentName = asNonEmptyString4(responsibility.name);
4727
4909
  if (!currentName && summary) {
4728
4910
  responsibility.name = summary;
4729
4911
  }
@@ -4755,7 +4937,7 @@ function parseSmartKpiViewCreateBody(raw) {
4755
4937
  }
4756
4938
  function normalizeSmartKpiViewCreateBody(body) {
4757
4939
  const smartKpiView = ensureEntityObject(body, "smart_kpi_view");
4758
- const name = asNonEmptyString3(smartKpiView.name);
4940
+ const name = asNonEmptyString4(smartKpiView.name);
4759
4941
  if (!name) {
4760
4942
  throwMissingRequiredCreateFields("smart_kpi_view", ["name"]);
4761
4943
  }
@@ -4793,9 +4975,9 @@ function buildKpisCreateMutation(params) {
4793
4975
  });
4794
4976
  }
4795
4977
  const smartKpi = { ...entity };
4796
- const name = asNonEmptyString3(smartKpi.name);
4797
- const smartKpiViewId = asNonEmptyString3(smartKpi.smart_kpi_view_id);
4798
- const measurableGroupId = asNonEmptyString3(smartKpi.measurable_group_id);
4978
+ const name = asNonEmptyString4(smartKpi.name);
4979
+ const smartKpiViewId = asNonEmptyString4(smartKpi.smart_kpi_view_id);
4980
+ const measurableGroupId = asNonEmptyString4(smartKpi.measurable_group_id);
4799
4981
  const hasAllowedName = typeof name === "string" && SMART_KPI_NAME_SET.has(name);
4800
4982
  if (!name) {
4801
4983
  throw new CliError({
@@ -4815,7 +4997,7 @@ function buildKpisCreateMutation(params) {
4815
4997
  measurable_type: "number",
4816
4998
  condition: "greater_than_or_equal_to"
4817
4999
  };
4818
- const notes = asNonEmptyString3(smartKpi.notes);
5000
+ const notes = asNonEmptyString4(smartKpi.notes);
4819
5001
  if (notes) {
4820
5002
  measurable.notes = notes;
4821
5003
  }
@@ -5218,7 +5400,7 @@ function ensureRootObject(body, rootKey) {
5218
5400
  }
5219
5401
  return { ...root };
5220
5402
  }
5221
- function asNonEmptyString4(value) {
5403
+ function asNonEmptyString5(value) {
5222
5404
  if (typeof value !== "string") {
5223
5405
  return void 0;
5224
5406
  }
@@ -5228,7 +5410,7 @@ function asNonEmptyString4(value) {
5228
5410
  function normalizeOrganizationUpdateBody(body) {
5229
5411
  const organization = ensureRootObject(body, "organization");
5230
5412
  const detail = isRecord3(organization.organization_detail_attributes) ? { ...organization.organization_detail_attributes } : {};
5231
- const workspaceName = asNonEmptyString4(organization.workspace_name);
5413
+ const workspaceName = asNonEmptyString5(organization.workspace_name);
5232
5414
  if (workspaceName) {
5233
5415
  detail.workspace_name = workspaceName;
5234
5416
  }
@@ -5241,7 +5423,7 @@ function normalizeOrganizationUpdateBody(body) {
5241
5423
  function normalizeOrganizationMetaProfileUpdateBody(body) {
5242
5424
  const root = ensureRootObject(body, "organization_meta_profile");
5243
5425
  const profile = isRecord3(root.profile) ? { ...root.profile } : {};
5244
- const title = asNonEmptyString4(root.title);
5426
+ const title = asNonEmptyString5(root.title);
5245
5427
  if (title) {
5246
5428
  const companyIdentity = isRecord3(profile.company_identity) ? { ...profile.company_identity } : {};
5247
5429
  companyIdentity.one_sentence_summary = title;
@@ -5271,7 +5453,7 @@ function normalizeOrganizationMetaProfileUpdateBody(body) {
5271
5453
  function normalizeKeyMetricMetaProfileUpdateBody(body) {
5272
5454
  const root = ensureRootObject(body, "key_metric_meta_profile");
5273
5455
  const profile = isRecord3(root.profile) ? { ...root.profile } : {};
5274
- const annualRevenue = asNonEmptyString4(root.annual_revenue);
5456
+ const annualRevenue = asNonEmptyString5(root.annual_revenue);
5275
5457
  if (annualRevenue) {
5276
5458
  const financial = isRecord3(profile.financial) ? { ...profile.financial } : {};
5277
5459
  financial.revenue = annualRevenue;
@@ -5442,7 +5624,7 @@ function ensureRootObject2(body, rootKey) {
5442
5624
  }
5443
5625
  return { ...root };
5444
5626
  }
5445
- function asNonEmptyString5(value) {
5627
+ function asNonEmptyString6(value) {
5446
5628
  if (typeof value !== "string") {
5447
5629
  return void 0;
5448
5630
  }
@@ -5470,8 +5652,8 @@ function normalizeStrategicPlanUpdateBody(body) {
5470
5652
  }
5471
5653
  function normalizeStrategicObjectiveUpdateBody(body) {
5472
5654
  const strategicObjective = ensureRootObject2(body, "strategic_objective");
5473
- const title = asNonEmptyString5(strategicObjective.title);
5474
- if (!asNonEmptyString5(strategicObjective.summary) && title) {
5655
+ const title = asNonEmptyString6(strategicObjective.title);
5656
+ if (!asNonEmptyString6(strategicObjective.summary) && title) {
5475
5657
  strategicObjective.summary = title;
5476
5658
  }
5477
5659
  delete strategicObjective.title;
@@ -5494,8 +5676,8 @@ function normalizeStrategicObjectiveUpdateBody(body) {
5494
5676
  }
5495
5677
  function normalizeAnnualObjectiveCreateBody(body) {
5496
5678
  const annualObjective = ensureRootObject2(body, "annual_objective");
5497
- const title = asNonEmptyString5(annualObjective.title);
5498
- if (!asNonEmptyString5(annualObjective.name) && title) {
5679
+ const title = asNonEmptyString6(annualObjective.title);
5680
+ if (!asNonEmptyString6(annualObjective.name) && title) {
5499
5681
  annualObjective.name = title;
5500
5682
  }
5501
5683
  delete annualObjective.title;
@@ -5503,8 +5685,8 @@ function normalizeAnnualObjectiveCreateBody(body) {
5503
5685
  }
5504
5686
  function normalizeQuarterlyObjectiveCreateBody(body) {
5505
5687
  const quarterlyObjective = ensureRootObject2(body, "quarterly_objective");
5506
- const title = asNonEmptyString5(quarterlyObjective.title);
5507
- if (!asNonEmptyString5(quarterlyObjective.name) && title) {
5688
+ const title = asNonEmptyString6(quarterlyObjective.title);
5689
+ if (!asNonEmptyString6(quarterlyObjective.name) && title) {
5508
5690
  quarterlyObjective.name = title;
5509
5691
  }
5510
5692
  delete quarterlyObjective.title;
@@ -6305,7 +6487,7 @@ var import_zod16 = require("zod");
6305
6487
 
6306
6488
  // src/internalOptions.ts
6307
6489
  var INTERNAL_OPTIONS_KEY = "__waveInternalOptions";
6308
- function asRecord5(value) {
6490
+ function asRecord6(value) {
6309
6491
  if (!value || typeof value !== "object" || Array.isArray(value)) {
6310
6492
  return null;
6311
6493
  }
@@ -6319,7 +6501,7 @@ function setInternalCliOptions(program, options) {
6319
6501
  function getInternalCliOptions(command) {
6320
6502
  let current = command;
6321
6503
  while (current) {
6322
- const record = asRecord5(current[INTERNAL_OPTIONS_KEY]);
6504
+ const record = asRecord6(current[INTERNAL_OPTIONS_KEY]);
6323
6505
  if (record) {
6324
6506
  return {
6325
6507
  enableRetryOnEmptyPhrase: record.enableRetryOnEmptyPhrase === true
@@ -9964,142 +10146,6 @@ function registerOsmdCommands(program) {
9964
10146
 
9965
10147
  // src/commands/auth.ts
9966
10148
  var import_node_child_process2 = require("child_process");
9967
-
9968
- // src/authClient.ts
9969
- var import_node_crypto2 = require("crypto");
9970
-
9971
- // src/redaction.ts
9972
- var TOKENISH_PATTERNS = [
9973
- /\b(?:cli|wave|token|secret|bearer)[A-Za-z0-9._~+/=-]{8,}\b/gi,
9974
- /\b[A-Za-z0-9._~+/=-]{24,}\b/g
9975
- ];
9976
- function redactOne(value) {
9977
- if (value.length <= 8) {
9978
- return "[redacted]";
9979
- }
9980
- return `${value.slice(0, 4)}...[redacted]...${value.slice(-4)}`;
9981
- }
9982
- function redactSecrets(input, knownSecrets = []) {
9983
- let output = input;
9984
- for (const secret of knownSecrets) {
9985
- if (!secret) continue;
9986
- output = output.split(secret).join(redactOne(secret));
9987
- }
9988
- for (const pattern of TOKENISH_PATTERNS) {
9989
- output = output.replace(pattern, (match) => redactOne(match));
9990
- }
9991
- return output;
9992
- }
9993
- function redactUnknown(input, knownSecrets = []) {
9994
- if (typeof input === "string") {
9995
- return redactSecrets(input, knownSecrets);
9996
- }
9997
- if (Array.isArray(input)) {
9998
- return input.map((entry2) => redactUnknown(entry2, knownSecrets));
9999
- }
10000
- if (!input || typeof input !== "object") {
10001
- return input;
10002
- }
10003
- const output = {};
10004
- for (const [key, value] of Object.entries(input)) {
10005
- if (/token|secret|authorization|bearer/i.test(key)) {
10006
- output[key] = typeof value === "string" ? redactSecrets(value, knownSecrets) : "[redacted]";
10007
- continue;
10008
- }
10009
- output[key] = redactUnknown(value, knownSecrets);
10010
- }
10011
- return output;
10012
- }
10013
-
10014
- // src/authClient.ts
10015
- function parseJsonSafely2(input) {
10016
- try {
10017
- return JSON.parse(input);
10018
- } catch {
10019
- return null;
10020
- }
10021
- }
10022
- function graphqlErrors(payload, knownSecrets) {
10023
- const errors = payload.errors;
10024
- if (!Array.isArray(errors) || errors.length === 0) return null;
10025
- return {
10026
- code: "upstream_error",
10027
- message: "GraphQL request failed.",
10028
- status: 400,
10029
- details: {
10030
- errors: redactUnknown(errors, knownSecrets)
10031
- }
10032
- };
10033
- }
10034
- async function authGraphqlRequest(params) {
10035
- const requestId = (0, import_node_crypto2.randomUUID)();
10036
- const controller = new AbortController();
10037
- const timeoutId = setTimeout(() => controller.abort(), params.timeoutMs);
10038
- const knownSecrets = [params.token, ...params.knownSecrets ?? []].filter(
10039
- (secret) => typeof secret === "string" && secret.length > 0
10040
- );
10041
- try {
10042
- const url = new URL("/graphql", params.baseUrl);
10043
- const response = await fetch(url, {
10044
- method: "POST",
10045
- headers: {
10046
- Accept: "application/json",
10047
- "Content-Type": "application/json",
10048
- "X-Origin": "wave-cli",
10049
- "X-Request-Id": requestId,
10050
- ...params.token ? { Authorization: `Bearer ${params.token}` } : {}
10051
- },
10052
- body: JSON.stringify({ query: params.query, variables: params.variables ?? {} }),
10053
- signal: controller.signal
10054
- });
10055
- const responseRequestId = response.headers.get("x-request-id") ?? requestId;
10056
- const text = await response.text();
10057
- const payload = text ? parseJsonSafely2(text) : null;
10058
- const graph = payload && typeof payload === "object" && !Array.isArray(payload) ? payload : {};
10059
- const gqlError = graphqlErrors(graph, knownSecrets);
10060
- if (gqlError) {
10061
- return { ok: false, error: gqlError, requestId: responseRequestId };
10062
- }
10063
- if (!response.ok) {
10064
- return {
10065
- ok: false,
10066
- requestId: responseRequestId,
10067
- error: {
10068
- code: `http_${response.status}`,
10069
- message: "Auth request failed.",
10070
- status: response.status,
10071
- details: { body: redactUnknown(graph, knownSecrets) }
10072
- }
10073
- };
10074
- }
10075
- const data = graph.data && typeof graph.data === "object" && !Array.isArray(graph.data) ? graph.data : {};
10076
- return {
10077
- ok: true,
10078
- result: {
10079
- status: response.status,
10080
- requestId: responseRequestId,
10081
- data
10082
- }
10083
- };
10084
- } catch (error) {
10085
- const message = error instanceof Error ? error.message : "Network error.";
10086
- const timedOut = error instanceof Error && error.name === "AbortError";
10087
- return {
10088
- ok: false,
10089
- requestId,
10090
- error: {
10091
- code: timedOut ? "timeout" : "network_error",
10092
- message: redactSecrets(timedOut ? "Auth request timed out." : message, knownSecrets),
10093
- status: timedOut ? 408 : 503,
10094
- details: {}
10095
- }
10096
- };
10097
- } finally {
10098
- clearTimeout(timeoutId);
10099
- }
10100
- }
10101
-
10102
- // src/commands/auth.ts
10103
10149
  var DEFAULT_LOGIN_TIMEOUT_MS = 12e4;
10104
10150
  var DEFAULT_POLL_INTERVAL_MS = 2e3;
10105
10151
  function envelope(params) {
@@ -10127,7 +10173,7 @@ function positiveInt2(raw, fallback) {
10127
10173
  function requestTimeoutMs(totalTimeoutMs) {
10128
10174
  return Math.max(1e3, Math.min(totalTimeoutMs, 1e4));
10129
10175
  }
10130
- function asRecord6(value) {
10176
+ function asRecord7(value) {
10131
10177
  return value && typeof value === "object" && !Array.isArray(value) ? value : null;
10132
10178
  }
10133
10179
  function asString(value) {
@@ -10174,9 +10220,9 @@ function cliTokenFromPoll(payload) {
10174
10220
  return asString(payload.cliToken) ?? asString(payload.cli_token) ?? asString(payload.token);
10175
10221
  }
10176
10222
  function unwrapMutationResult(value) {
10177
- const record = asRecord6(value);
10223
+ const record = asRecord7(value);
10178
10224
  if (!record) return null;
10179
- const data = asRecord6(record.data);
10225
+ const data = asRecord7(record.data);
10180
10226
  if (data && (Object.prototype.hasOwnProperty.call(record, "ok") || Object.prototype.hasOwnProperty.call(record, "errors") || Object.prototype.hasOwnProperty.call(record, "errorCode") || Object.prototype.hasOwnProperty.call(record, "error_code"))) {
10181
10227
  return data;
10182
10228
  }
@@ -10240,7 +10286,7 @@ async function runTokenLogin(cmd, opts) {
10240
10286
  exitCode: mapStatusToExitCode(status.error.status)
10241
10287
  });
10242
10288
  }
10243
- const statusData = asRecord6(status.result.data.cliAuthStatus) ?? {};
10289
+ const statusData = asRecord7(status.result.data.cliAuthStatus) ?? {};
10244
10290
  const storage = await writeStoredToken(token, baseUrl);
10245
10291
  const configPath2 = opts.saveBaseUrl ? await persistBaseUrl(baseUrl) : void 0;
10246
10292
  return printEnvelopeAndExit({
@@ -10457,7 +10503,7 @@ async function runLogout(cmd) {
10457
10503
  });
10458
10504
  if (result.ok) {
10459
10505
  requestId = result.result.requestId;
10460
- const payload = asRecord6(result.result.data.revokeCliToken) ?? {};
10506
+ const payload = asRecord7(result.result.data.revokeCliToken) ?? {};
10461
10507
  revokedRemote = payload.ok !== false;
10462
10508
  } else {
10463
10509
  requestId = result.requestId;
@@ -10520,7 +10566,8 @@ async function runAuthStatus(cmd) {
10520
10566
  exitCode: mapStatusToExitCode(result.error.status)
10521
10567
  });
10522
10568
  }
10523
- const status = asRecord6(result.result.data.cliAuthStatus) ?? {};
10569
+ const status = asRecord7(result.result.data.cliAuthStatus) ?? {};
10570
+ const baseAuthStatus = status.baseAuthStatus;
10524
10571
  return printEnvelopeAndExit({
10525
10572
  envelope: envelope({
10526
10573
  ok: true,
@@ -10529,6 +10576,7 @@ async function runAuthStatus(cmd) {
10529
10576
  requestId: result.result.requestId,
10530
10577
  data: {
10531
10578
  authenticated: Boolean(status.authenticated),
10579
+ baseAuthStatus: typeof baseAuthStatus === "string" ? baseAuthStatus : null,
10532
10580
  baseUrl,
10533
10581
  tokenSource,
10534
10582
  member: redactUnknown(status.member, [token]) ?? null,
@@ -12169,11 +12217,11 @@ function sanitizePlannerJson(value) {
12169
12217
  }
12170
12218
  return output;
12171
12219
  }
12172
- function asRecord7(value) {
12220
+ function asRecord8(value) {
12173
12221
  return value && typeof value === "object" && !Array.isArray(value) ? value : null;
12174
12222
  }
12175
12223
  function readPlannerStateKey(value, keys) {
12176
- const record = asRecord7(value);
12224
+ const record = asRecord8(value);
12177
12225
  if (!record) {
12178
12226
  return null;
12179
12227
  }
@@ -15798,7 +15846,7 @@ function attachDiscoveryHelp(program) {
15798
15846
  }
15799
15847
 
15800
15848
  // src/version.ts
15801
- var CLI_VERSION = "0.1.59";
15849
+ var CLI_VERSION = "0.1.61";
15802
15850
 
15803
15851
  // src/cli.ts
15804
15852
  function buildCli(options) {