@wave-ai-os/wave-cli 0.1.87 → 0.1.88

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.cjs CHANGED
@@ -8,6 +8,225 @@ var import_zod22 = require("zod");
8
8
  // src/cli.ts
9
9
  var import_commander2 = require("commander");
10
10
 
11
+ // src/authStorage.ts
12
+ var import_node_child_process = require("child_process");
13
+ var import_node_fs = require("fs");
14
+ var import_promises = require("fs/promises");
15
+ var import_node_os = require("os");
16
+ var import_node_path = require("path");
17
+ var import_node_util = require("util");
18
+ var execFileAsync = (0, import_node_util.promisify)(import_node_child_process.execFile);
19
+ var KEYCHAIN_SERVICE = "wave-cli";
20
+ var FILE_NAME = "auth-token.json";
21
+ var DEFAULT_STORAGE_MODE = "auto";
22
+ var activeOptions = {};
23
+ function configureAuthStorage(options) {
24
+ activeOptions = { ...options };
25
+ }
26
+ async function withAuthStorageOptions(options, callback) {
27
+ const previous = activeOptions;
28
+ activeOptions = { ...options };
29
+ try {
30
+ return await callback();
31
+ } finally {
32
+ activeOptions = previous;
33
+ }
34
+ }
35
+ function normalize(raw) {
36
+ if (typeof raw !== "string") return void 0;
37
+ const trimmed = raw.trim();
38
+ return trimmed.length > 0 ? trimmed : void 0;
39
+ }
40
+ function authHome() {
41
+ return normalize(activeOptions.home) ?? (0, import_node_path.join)((0, import_node_os.homedir)(), ".wave");
42
+ }
43
+ function tokenPath() {
44
+ return (0, import_node_path.join)(authHome(), FILE_NAME);
45
+ }
46
+ function configPath() {
47
+ return normalize(activeOptions.configPath) ?? (0, import_node_path.join)(authHome(), "config.json");
48
+ }
49
+ function storageMode() {
50
+ return activeOptions.mode ?? DEFAULT_STORAGE_MODE;
51
+ }
52
+ function accountForBaseUrl(baseUrl) {
53
+ return normalize(baseUrl) ?? "default";
54
+ }
55
+ async function commandExists(command) {
56
+ try {
57
+ await (0, import_promises.access)(command, import_node_fs.constants.X_OK);
58
+ return true;
59
+ } catch {
60
+ return false;
61
+ }
62
+ }
63
+ async function keychainAvailable() {
64
+ if (process.platform !== "darwin") return false;
65
+ if (storageMode() === "file" || storageMode() === "disabled") return false;
66
+ return commandExists("/usr/bin/security");
67
+ }
68
+ async function preferredStorage() {
69
+ const mode = storageMode();
70
+ if (mode === "disabled") return "disabled";
71
+ if (mode === "file") return "file";
72
+ if (mode === "keychain") return await keychainAvailable() ? "keychain" : "file";
73
+ return await keychainAvailable() ? "keychain" : "file";
74
+ }
75
+ async function readKeychainToken(baseUrl) {
76
+ try {
77
+ const { stdout } = await execFileAsync("/usr/bin/security", [
78
+ "find-generic-password",
79
+ "-a",
80
+ accountForBaseUrl(baseUrl),
81
+ "-s",
82
+ KEYCHAIN_SERVICE,
83
+ "-w"
84
+ ], { encoding: "utf8" });
85
+ return normalize(String(stdout)) ?? null;
86
+ } catch {
87
+ return null;
88
+ }
89
+ }
90
+ async function writeKeychainToken(token, baseUrl) {
91
+ await execFileAsync("/usr/bin/security", [
92
+ "add-generic-password",
93
+ "-a",
94
+ accountForBaseUrl(baseUrl),
95
+ "-s",
96
+ KEYCHAIN_SERVICE,
97
+ "-w",
98
+ token,
99
+ "-U"
100
+ ]);
101
+ }
102
+ async function deleteKeychainToken(baseUrl) {
103
+ try {
104
+ await execFileAsync("/usr/bin/security", [
105
+ "delete-generic-password",
106
+ "-a",
107
+ accountForBaseUrl(baseUrl),
108
+ "-s",
109
+ KEYCHAIN_SERVICE
110
+ ]);
111
+ return true;
112
+ } catch {
113
+ return false;
114
+ }
115
+ }
116
+ async function readFileToken(baseUrl) {
117
+ const path = tokenPath();
118
+ if (!(0, import_node_fs.existsSync)(path)) return null;
119
+ try {
120
+ const raw = await (0, import_promises.readFile)(path, "utf8");
121
+ const payload = JSON.parse(raw);
122
+ const token = normalize(payload.token);
123
+ const storedBaseUrl = normalize(payload.baseUrl);
124
+ const requestedBaseUrl = normalize(baseUrl);
125
+ if (!token) return null;
126
+ if (storedBaseUrl !== requestedBaseUrl) return null;
127
+ return token;
128
+ } catch {
129
+ return null;
130
+ }
131
+ }
132
+ async function writeFileToken(token, baseUrl) {
133
+ const home = authHome();
134
+ const path = tokenPath();
135
+ await (0, import_promises.mkdir)(home, { recursive: true, mode: 448 });
136
+ await (0, import_promises.writeFile)(
137
+ path,
138
+ `${JSON.stringify({ token, baseUrl: baseUrl ?? null, updatedAt: (/* @__PURE__ */ new Date()).toISOString() })}
139
+ `,
140
+ { mode: 384 }
141
+ );
142
+ await (0, import_promises.chmod)(path, 384);
143
+ }
144
+ async function deleteFileToken() {
145
+ const path = tokenPath();
146
+ if (!(0, import_node_fs.existsSync)(path)) return false;
147
+ await (0, import_promises.rm)(path, { force: true });
148
+ return true;
149
+ }
150
+ async function readStoredToken(baseUrl) {
151
+ const mode = await preferredStorage();
152
+ if (mode === "disabled") return null;
153
+ if (mode === "keychain") {
154
+ const keychainToken = await readKeychainToken(baseUrl);
155
+ if (keychainToken) return { token: keychainToken, source: "keychain" };
156
+ }
157
+ const fileToken = await readFileToken(baseUrl);
158
+ return fileToken ? { token: fileToken, source: "file" } : null;
159
+ }
160
+ async function writeStoredToken(token, baseUrl) {
161
+ const mode = await preferredStorage();
162
+ if (mode === "disabled") {
163
+ return { kind: "disabled", available: false };
164
+ }
165
+ if (mode === "keychain") {
166
+ try {
167
+ await writeKeychainToken(token, baseUrl);
168
+ return {
169
+ kind: "keychain",
170
+ available: true,
171
+ service: KEYCHAIN_SERVICE,
172
+ account: accountForBaseUrl(baseUrl)
173
+ };
174
+ } catch {
175
+ await writeFileToken(token, baseUrl);
176
+ return { kind: "file", available: true, path: tokenPath() };
177
+ }
178
+ }
179
+ await writeFileToken(token, baseUrl);
180
+ return { kind: "file", available: true, path: tokenPath() };
181
+ }
182
+ async function persistBaseUrl(baseUrl) {
183
+ const path = configPath();
184
+ let existing = {};
185
+ if ((0, import_node_fs.existsSync)(path)) {
186
+ const raw = await (0, import_promises.readFile)(path, "utf8");
187
+ const parsed = JSON.parse(raw);
188
+ if (!parsed || typeof parsed !== "object" || Array.isArray(parsed)) {
189
+ throw new Error(`Wave config file must contain a JSON object: ${path}`);
190
+ }
191
+ existing = parsed;
192
+ }
193
+ await (0, import_promises.mkdir)((0, import_node_path.dirname)(path), { recursive: true, mode: 448 });
194
+ await (0, import_promises.writeFile)(path, `${JSON.stringify({ ...existing, baseUrl }, null, 2)}
195
+ `, {
196
+ mode: 384
197
+ });
198
+ await (0, import_promises.chmod)(path, 384);
199
+ return path;
200
+ }
201
+ async function removeStoredToken(baseUrl) {
202
+ const removedKeychain = await deleteKeychainToken(baseUrl);
203
+ const removedFile = await deleteFileToken();
204
+ return removedKeychain || removedFile;
205
+ }
206
+ async function getAuthStorageInfo(baseUrl) {
207
+ const mode = await preferredStorage();
208
+ if (mode === "disabled") return { kind: "disabled", available: false };
209
+ if (mode === "keychain") {
210
+ return {
211
+ kind: "keychain",
212
+ available: true,
213
+ service: KEYCHAIN_SERVICE,
214
+ account: accountForBaseUrl(baseUrl)
215
+ };
216
+ }
217
+ const path = tokenPath();
218
+ let available = true;
219
+ if ((0, import_node_fs.existsSync)(path)) {
220
+ try {
221
+ const modeBits = (await (0, import_promises.stat)(path)).mode & 511;
222
+ available = modeBits === 384;
223
+ } catch {
224
+ available = false;
225
+ }
226
+ }
227
+ return { kind: "file", available, path };
228
+ }
229
+
11
230
  // src/commands/tasks.ts
12
231
  var import_zod3 = require("zod");
13
232
 
@@ -192,7 +411,7 @@ var ATLAS_LEDGER_VARIABLE_TYPES = {
192
411
  };
193
412
  var SECRET_KEY_PATTERN = /(authorization|password|passwd|secret|token|jwt|credential|api[_-]?key)/i;
194
413
  var MAX_EVIDENCE_DEPTH = 5;
195
- function normalize(raw) {
414
+ function normalize2(raw) {
196
415
  if (typeof raw !== "string") {
197
416
  return void 0;
198
417
  }
@@ -200,12 +419,12 @@ function normalize(raw) {
200
419
  return trimmed.length > 0 ? trimmed : void 0;
201
420
  }
202
421
  function atlasContextFromConfig(config) {
203
- const organizationId = normalize(config.organizationId);
204
- const memberId = normalize(config.atlasMemberId);
205
- const chatId = normalize(config.atlasChatId);
206
- const assistantMessageId = normalize(config.atlasAssistantMessageId);
207
- const activeTool = normalize(config.atlasActiveTool);
208
- const targetTool = normalize(config.atlasTargetTool);
422
+ const organizationId = normalize2(config.organizationId);
423
+ const memberId = normalize2(config.atlasMemberId);
424
+ const chatId = normalize2(config.atlasChatId);
425
+ const assistantMessageId = normalize2(config.atlasAssistantMessageId);
426
+ const activeTool = normalize2(config.atlasActiveTool);
427
+ const targetTool = normalize2(config.atlasTargetTool);
209
428
  if (!organizationId || !memberId || !chatId || !assistantMessageId || !activeTool || !targetTool) {
210
429
  return null;
211
430
  }
@@ -216,8 +435,8 @@ function atlasContextFromConfig(config) {
216
435
  assistantMessageId,
217
436
  activeTool,
218
437
  targetTool,
219
- routeReason: normalize(config.atlasRouteReason),
220
- actionId: normalize(config.atlasActionId)
438
+ routeReason: normalize2(config.atlasRouteReason),
439
+ actionId: normalize2(config.atlasActionId)
221
440
  };
222
441
  }
223
442
  function summarizeVariableShape(value, key = void 0, depth = 0) {
@@ -253,7 +472,7 @@ function shouldReportAtlasActionLedgerEvent(input) {
253
472
  return input.operationType === "mutation" && input.field !== ATLAS_LEDGER_FIELD;
254
473
  }
255
474
  function deterministicAtlasActionId(input, config) {
256
- const requestSegment = normalize(config.requestId) ? `:${config.requestId}` : "";
475
+ const requestSegment = normalize2(config.requestId) ? `:${config.requestId}` : "";
257
476
  return `cli:${input.command}:${input.field}${requestSegment}`;
258
477
  }
259
478
  function buildAtlasEvidenceRefs(params) {
@@ -584,118 +803,6 @@ function buildSparse422Diagnostic(input) {
584
803
  }
585
804
  };
586
805
  }
587
- function isFeedbackCreateCommand(input) {
588
- return input.operationType === "mutation" && input.command === "feedbacks.create";
589
- }
590
- function asRecord(value) {
591
- if (!value || typeof value !== "object" || Array.isArray(value)) {
592
- return null;
593
- }
594
- return value;
595
- }
596
- function asNonEmptyString(value) {
597
- if (typeof value !== "string") {
598
- return null;
599
- }
600
- const trimmed = value.trim();
601
- return trimmed.length > 0 ? trimmed : null;
602
- }
603
- function extractFeedbackIdentity(variables) {
604
- const organizationId = asNonEmptyString(variables.organization_id) ?? asNonEmptyString(variables.organizationId);
605
- const params = asRecord(variables.params);
606
- const feedback = params ? asRecord(params.feedback) : null;
607
- const name = feedback ? asNonEmptyString(feedback.name) : null;
608
- const quarter = feedback ? asNonEmptyString(feedback.quarter) : null;
609
- const year = feedback ? asNonEmptyString(feedback.year) : null;
610
- if (!organizationId || !name || !quarter || !year) {
611
- return null;
612
- }
613
- return {
614
- organizationId,
615
- name,
616
- quarter,
617
- year
618
- };
619
- }
620
- function collectMessageStrings(value) {
621
- if (typeof value === "string") {
622
- return [value];
623
- }
624
- if (Array.isArray(value)) {
625
- return value.flatMap((entry2) => collectMessageStrings(entry2));
626
- }
627
- if (!value || typeof value !== "object") {
628
- return [];
629
- }
630
- return Object.values(value).flatMap(
631
- (entry2) => collectMessageStrings(entry2)
632
- );
633
- }
634
- function isDuplicateFeedbackMutationError(mutationPayload) {
635
- const messages = collectMessageStrings(mutationPayload.errors);
636
- return messages.some(
637
- (message) => message.toLowerCase().includes("already been taken")
638
- );
639
- }
640
- function extractFeedbackListNode(graph) {
641
- const data = asRecord(graph.data);
642
- const feedbacks = data ? asRecord(data.feedbacks) : null;
643
- if (!feedbacks) {
644
- return null;
645
- }
646
- const rows = Array.isArray(feedbacks.data) ? feedbacks.data : [];
647
- const first = rows.find((entry2) => asRecord(entry2));
648
- return first ? first : null;
649
- }
650
- function buildFeedbackReuseEnvelope(params) {
651
- return {
652
- envelope: buildEnvelope({
653
- ok: true,
654
- command: params.command,
655
- status: params.status,
656
- data: {
657
- [params.field]: {
658
- ok: true,
659
- status: params.status,
660
- errorCode: null,
661
- data: {
662
- data: params.feedbackNode
663
- },
664
- errors: null,
665
- reusedExisting: true,
666
- idempotency: {
667
- reason: params.reason
668
- }
669
- }
670
- },
671
- error: null,
672
- requestId: params.requestId
673
- }),
674
- exitCode: EXIT_CODES.success
675
- };
676
- }
677
- function buildFeedbackFindRequestBody(command, identity) {
678
- return buildGraphqlBody({
679
- config: {
680
- baseUrl: "http://localhost",
681
- token: "placeholder",
682
- timeoutMs: 1e3,
683
- debug: false
684
- },
685
- command,
686
- operationType: "query",
687
- field: "feedbacks",
688
- variables: {
689
- organization_id: identity.organizationId,
690
- name: identity.name,
691
- quarter: identity.quarter,
692
- year: identity.year,
693
- page: 1,
694
- per: 1
695
- },
696
- selectionSet: "{ data { id type attributes { id name slug year quarter organizationId memberIds } } count currentPage totalPages }"
697
- });
698
- }
699
806
  async function requestGraphqlHttp(params) {
700
807
  const response = await fetch(params.url, {
701
808
  method: "POST",
@@ -787,29 +894,6 @@ async function finalizeGraphqlResult(input, url, result) {
787
894
  }
788
895
  return result;
789
896
  }
790
- async function findExistingFeedback(params) {
791
- const command = `${params.input.command}.find-existing`;
792
- const body = buildFeedbackFindRequestBody(command, params.identity);
793
- const http = await requestGraphqlHttp({
794
- input: params.input,
795
- url: params.url,
796
- requestId: params.requestId,
797
- body,
798
- controller: params.controller
799
- });
800
- const gqlErrors = http.graph.errors;
801
- if (Array.isArray(gqlErrors) && gqlErrors.length > 0) {
802
- return null;
803
- }
804
- const feedbackNode = extractFeedbackListNode(http.graph);
805
- if (!feedbackNode) {
806
- return null;
807
- }
808
- return {
809
- feedbackNode,
810
- requestId: http.requestId
811
- };
812
- }
813
897
  function graphqlTypeForValue(value) {
814
898
  if (Array.isArray(value)) {
815
899
  const firstNonNull = value.find((item) => item !== null && item !== void 0);
@@ -909,32 +993,6 @@ async function graphqlRequest(input) {
909
993
  const controller = new AbortController();
910
994
  const timeoutId = setTimeout(() => controller.abort(), input.config.timeoutMs);
911
995
  try {
912
- if (isFeedbackCreateCommand(input)) {
913
- const feedbackIdentity = extractFeedbackIdentity(input.variables);
914
- if (feedbackIdentity) {
915
- const existing = await findExistingFeedback({
916
- input,
917
- url,
918
- requestId,
919
- controller,
920
- identity: feedbackIdentity
921
- });
922
- if (existing) {
923
- return finalizeGraphqlResult(
924
- input,
925
- url,
926
- buildFeedbackReuseEnvelope({
927
- command: input.command,
928
- field: input.field,
929
- status: 200,
930
- requestId: existing.requestId,
931
- feedbackNode: existing.feedbackNode,
932
- reason: "preexisting"
933
- })
934
- );
935
- }
936
- }
937
- }
938
996
  const http = await requestGraphqlHttpWithRetry({
939
997
  input,
940
998
  url,
@@ -979,32 +1037,6 @@ async function graphqlRequest(input) {
979
1037
  const ok = Boolean(mutationPayload.ok);
980
1038
  const status = typeof mutationPayload.status === "number" ? mutationPayload.status : ok ? 200 : 400;
981
1039
  if (!ok) {
982
- if (isFeedbackCreateCommand(input) && isDuplicateFeedbackMutationError(mutationPayload)) {
983
- const feedbackIdentity = extractFeedbackIdentity(input.variables);
984
- if (feedbackIdentity) {
985
- const existing = await findExistingFeedback({
986
- input,
987
- url,
988
- requestId: responseRequestId,
989
- controller,
990
- identity: feedbackIdentity
991
- });
992
- if (existing) {
993
- return finalizeGraphqlResult(
994
- input,
995
- url,
996
- buildFeedbackReuseEnvelope({
997
- command: input.command,
998
- field: input.field,
999
- status: 200,
1000
- requestId: existing.requestId,
1001
- feedbackNode: existing.feedbackNode,
1002
- reason: "duplicate_race"
1003
- })
1004
- );
1005
- }
1006
- }
1007
- }
1008
1040
  const mutationErrors = mutationPayload.errors ?? null;
1009
1041
  const details = {
1010
1042
  errors: mutationErrors,
@@ -1094,7 +1126,7 @@ async function graphqlRequest(input) {
1094
1126
  }
1095
1127
 
1096
1128
  // src/output.ts
1097
- var import_node_fs = require("fs");
1129
+ var import_node_fs2 = require("fs");
1098
1130
  var RETRYABLE_WRITE_CODES = /* @__PURE__ */ new Set(["EAGAIN", "EINTR"]);
1099
1131
  var RETRY_BACKOFF_MS = 1;
1100
1132
  var EnvelopeEmittedSignal = class extends Error {
@@ -1113,7 +1145,7 @@ function writeStdoutFully(text) {
1113
1145
  let offset = 0;
1114
1146
  while (offset < buffer.length) {
1115
1147
  try {
1116
- const bytesWritten = (0, import_node_fs.writeSync)(fd, buffer, offset, buffer.length - offset);
1148
+ const bytesWritten = (0, import_node_fs2.writeSync)(fd, buffer, offset, buffer.length - offset);
1117
1149
  if (bytesWritten <= 0) {
1118
1150
  sleepBriefly(RETRY_BACKOFF_MS);
1119
1151
  continue;
@@ -1460,14 +1492,6 @@ var RESOURCE_QUERY_FIELDS = {
1460
1492
  "acceptedAnswerIds",
1461
1493
  "labelIds"
1462
1494
  ],
1463
- feedback: [
1464
- "name",
1465
- "slug",
1466
- "year",
1467
- "quarter",
1468
- "organizationId",
1469
- "memberIds"
1470
- ],
1471
1495
  survey: [
1472
1496
  "name",
1473
1497
  "slug",
@@ -1629,7 +1653,6 @@ var RESOURCE_FIELD_ALIASES = {
1629
1653
  stand_ups: "stand_up",
1630
1654
  headlines: "headline",
1631
1655
  questions: "question",
1632
- feedbacks: "feedback",
1633
1656
  surveys: "survey",
1634
1657
  responsibilities: "responsibility",
1635
1658
  smart_kpi_views: "smart_kpi_view",
@@ -1876,222 +1899,15 @@ async function runGraphqlMutationCommand(input) {
1876
1899
  message
1877
1900
  }),
1878
1901
  exitCode: EXIT_CODES.generic
1879
- });
1880
- }
1881
- }
1882
-
1883
- // src/commands/runtimeOptions.ts
1884
- var import_node_fs3 = require("fs");
1885
- var import_promises2 = require("fs/promises");
1886
- var import_node_path2 = require("path");
1887
-
1888
- // src/authStorage.ts
1889
- var import_node_child_process = require("child_process");
1890
- var import_node_fs2 = require("fs");
1891
- var import_promises = require("fs/promises");
1892
- var import_node_os = require("os");
1893
- var import_node_path = require("path");
1894
- var import_node_util = require("util");
1895
- var execFileAsync = (0, import_node_util.promisify)(import_node_child_process.execFile);
1896
- var KEYCHAIN_SERVICE = "wave-cli";
1897
- var FILE_NAME = "auth-token.json";
1898
- function normalize2(raw) {
1899
- if (typeof raw !== "string") return void 0;
1900
- const trimmed = raw.trim();
1901
- return trimmed.length > 0 ? trimmed : void 0;
1902
- }
1903
- function authHome(env = process.env) {
1904
- return normalize2(env.WAVE_CLI_HOME) ?? (0, import_node_path.join)((0, import_node_os.homedir)(), ".wave");
1905
- }
1906
- function tokenPath(env = process.env) {
1907
- return (0, import_node_path.join)(authHome(env), FILE_NAME);
1908
- }
1909
- function configPath(env = process.env) {
1910
- return normalize2(env.WAVE_CONFIG_PATH) ?? (0, import_node_path.join)(authHome(env), "config.json");
1911
- }
1912
- function storageMode(env = process.env) {
1913
- const raw = normalize2(env.WAVE_CLI_AUTH_STORAGE)?.toLowerCase();
1914
- if (raw === "keychain" || raw === "file" || raw === "disabled") return raw;
1915
- return "auto";
1916
- }
1917
- function accountForBaseUrl(baseUrl) {
1918
- return normalize2(baseUrl) ?? "default";
1919
- }
1920
- async function commandExists(command) {
1921
- try {
1922
- await (0, import_promises.access)(command, import_node_fs2.constants.X_OK);
1923
- return true;
1924
- } catch {
1925
- return false;
1926
- }
1927
- }
1928
- async function keychainAvailable(env = process.env) {
1929
- if (process.platform !== "darwin") return false;
1930
- if (storageMode(env) === "file" || storageMode(env) === "disabled") return false;
1931
- return commandExists("/usr/bin/security");
1932
- }
1933
- async function preferredStorage(env = process.env) {
1934
- const mode = storageMode(env);
1935
- if (mode === "disabled") return "disabled";
1936
- if (mode === "file") return "file";
1937
- if (mode === "keychain") return await keychainAvailable(env) ? "keychain" : "file";
1938
- return await keychainAvailable(env) ? "keychain" : "file";
1939
- }
1940
- async function readKeychainToken(baseUrl) {
1941
- try {
1942
- const { stdout } = await execFileAsync("/usr/bin/security", [
1943
- "find-generic-password",
1944
- "-a",
1945
- accountForBaseUrl(baseUrl),
1946
- "-s",
1947
- KEYCHAIN_SERVICE,
1948
- "-w"
1949
- ], { encoding: "utf8" });
1950
- return normalize2(String(stdout)) ?? null;
1951
- } catch {
1952
- return null;
1953
- }
1954
- }
1955
- async function writeKeychainToken(token, baseUrl) {
1956
- await execFileAsync("/usr/bin/security", [
1957
- "add-generic-password",
1958
- "-a",
1959
- accountForBaseUrl(baseUrl),
1960
- "-s",
1961
- KEYCHAIN_SERVICE,
1962
- "-w",
1963
- token,
1964
- "-U"
1965
- ]);
1966
- }
1967
- async function deleteKeychainToken(baseUrl) {
1968
- try {
1969
- await execFileAsync("/usr/bin/security", [
1970
- "delete-generic-password",
1971
- "-a",
1972
- accountForBaseUrl(baseUrl),
1973
- "-s",
1974
- KEYCHAIN_SERVICE
1975
- ]);
1976
- return true;
1977
- } catch {
1978
- return false;
1979
- }
1980
- }
1981
- async function readFileToken(baseUrl, env = process.env) {
1982
- const path = tokenPath(env);
1983
- if (!(0, import_node_fs2.existsSync)(path)) return null;
1984
- try {
1985
- const raw = await (0, import_promises.readFile)(path, "utf8");
1986
- const payload = JSON.parse(raw);
1987
- const token = normalize2(payload.token);
1988
- const storedBaseUrl = normalize2(payload.baseUrl);
1989
- const requestedBaseUrl = normalize2(baseUrl);
1990
- if (!token) return null;
1991
- if (storedBaseUrl !== requestedBaseUrl) return null;
1992
- return token;
1993
- } catch {
1994
- return null;
1995
- }
1996
- }
1997
- async function writeFileToken(token, baseUrl, env = process.env) {
1998
- const home = authHome(env);
1999
- const path = tokenPath(env);
2000
- await (0, import_promises.mkdir)(home, { recursive: true, mode: 448 });
2001
- await (0, import_promises.writeFile)(
2002
- path,
2003
- `${JSON.stringify({ token, baseUrl: baseUrl ?? null, updatedAt: (/* @__PURE__ */ new Date()).toISOString() })}
2004
- `,
2005
- { mode: 384 }
2006
- );
2007
- await (0, import_promises.chmod)(path, 384);
2008
- }
2009
- async function deleteFileToken(env = process.env) {
2010
- const path = tokenPath(env);
2011
- if (!(0, import_node_fs2.existsSync)(path)) return false;
2012
- await (0, import_promises.rm)(path, { force: true });
2013
- return true;
2014
- }
2015
- async function readStoredToken(baseUrl) {
2016
- const mode = await preferredStorage();
2017
- if (mode === "disabled") return null;
2018
- if (mode === "keychain") {
2019
- const keychainToken = await readKeychainToken(baseUrl);
2020
- if (keychainToken) return { token: keychainToken, source: "keychain" };
2021
- }
2022
- const fileToken = await readFileToken(baseUrl);
2023
- return fileToken ? { token: fileToken, source: "file" } : null;
2024
- }
2025
- async function writeStoredToken(token, baseUrl) {
2026
- const mode = await preferredStorage();
2027
- if (mode === "disabled") {
2028
- return { kind: "disabled", available: false };
2029
- }
2030
- if (mode === "keychain") {
2031
- try {
2032
- await writeKeychainToken(token, baseUrl);
2033
- return {
2034
- kind: "keychain",
2035
- available: true,
2036
- service: KEYCHAIN_SERVICE,
2037
- account: accountForBaseUrl(baseUrl)
2038
- };
2039
- } catch {
2040
- await writeFileToken(token, baseUrl);
2041
- return { kind: "file", available: true, path: tokenPath() };
2042
- }
2043
- }
2044
- await writeFileToken(token, baseUrl);
2045
- return { kind: "file", available: true, path: tokenPath() };
2046
- }
2047
- async function persistBaseUrl(baseUrl, env = process.env) {
2048
- const path = configPath(env);
2049
- let existing = {};
2050
- if ((0, import_node_fs2.existsSync)(path)) {
2051
- const raw = await (0, import_promises.readFile)(path, "utf8");
2052
- const parsed = JSON.parse(raw);
2053
- if (!parsed || typeof parsed !== "object" || Array.isArray(parsed)) {
2054
- throw new Error(`Wave config file must contain a JSON object: ${path}`);
2055
- }
2056
- existing = parsed;
2057
- }
2058
- await (0, import_promises.mkdir)((0, import_node_path.dirname)(path), { recursive: true, mode: 448 });
2059
- await (0, import_promises.writeFile)(path, `${JSON.stringify({ ...existing, baseUrl }, null, 2)}
2060
- `, {
2061
- mode: 384
2062
- });
2063
- await (0, import_promises.chmod)(path, 384);
2064
- return path;
2065
- }
2066
- async function removeStoredToken(baseUrl) {
2067
- const removedKeychain = await deleteKeychainToken(baseUrl);
2068
- const removedFile = await deleteFileToken();
2069
- return removedKeychain || removedFile;
2070
- }
2071
- async function getAuthStorageInfo(baseUrl) {
2072
- const mode = await preferredStorage();
2073
- if (mode === "disabled") return { kind: "disabled", available: false };
2074
- if (mode === "keychain") {
2075
- return {
2076
- kind: "keychain",
2077
- available: true,
2078
- service: KEYCHAIN_SERVICE,
2079
- account: accountForBaseUrl(baseUrl)
2080
- };
2081
- }
2082
- const path = tokenPath();
2083
- let available = true;
2084
- if ((0, import_node_fs2.existsSync)(path)) {
2085
- try {
2086
- const modeBits = (await (0, import_promises.stat)(path)).mode & 511;
2087
- available = modeBits === 384;
2088
- } catch {
2089
- available = false;
2090
- }
1902
+ });
2091
1903
  }
2092
- return { kind: "file", available, path };
2093
1904
  }
2094
1905
 
1906
+ // src/commands/runtimeOptions.ts
1907
+ var import_node_fs3 = require("fs");
1908
+ var import_promises2 = require("fs/promises");
1909
+ var import_node_path2 = require("path");
1910
+
2095
1911
  // src/authClient.ts
2096
1912
  var import_node_crypto2 = require("crypto");
2097
1913
 
@@ -2538,17 +2354,15 @@ async function resolveWithAuthenticatedOrganization(context) {
2538
2354
  if (organizationId) resolved.organizationId = organizationId;
2539
2355
  return resolved;
2540
2356
  }
2541
- function defaultConfigPath(env) {
2542
- const explicitEnv = normalize3(env.WAVE_CONFIG_PATH);
2543
- if (explicitEnv) return explicitEnv;
2544
- const candidate = (0, import_node_path2.join)(authHome(env), "config.json");
2357
+ function defaultConfigPath() {
2358
+ const candidate = (0, import_node_path2.join)(authHome(), "config.json");
2545
2359
  return (0, import_node_fs3.existsSync)(candidate) ? candidate : void 0;
2546
2360
  }
2547
2361
  async function resolveConfigFileContext(options, env) {
2548
2362
  const path = firstDefined(
2549
2363
  normalize3(options.configPath),
2550
2364
  normalize3(options.config),
2551
- defaultConfigPath(env)
2365
+ defaultConfigPath()
2552
2366
  );
2553
2367
  if (!path) return {};
2554
2368
  if (!(0, import_node_fs3.existsSync)(path)) {
@@ -2693,13 +2507,13 @@ function parseRequiredOption(raw, flag) {
2693
2507
  function optionKey(flag) {
2694
2508
  return flag.replace(/-([a-z])/g, (_, char) => char.toUpperCase());
2695
2509
  }
2696
- function asRecord2(value) {
2510
+ function asRecord(value) {
2697
2511
  return value && typeof value === "object" && !Array.isArray(value) ? value : null;
2698
2512
  }
2699
2513
  function visibleSearchText(row) {
2700
- const record = asRecord2(row);
2514
+ const record = asRecord(row);
2701
2515
  if (!record) return "";
2702
- const attributes = asRecord2(record.attributes);
2516
+ const attributes = asRecord(record.attributes);
2703
2517
  const values = [];
2704
2518
  for (const field of SEARCHABLE_VISIBLE_FIELDS) {
2705
2519
  const topLevelValue = record[field];
@@ -2713,7 +2527,7 @@ function matchesSearchQuery(row, query) {
2713
2527
  return visibleSearchText(row).includes(query.toLowerCase());
2714
2528
  }
2715
2529
  function filterListEnvelopeByQuery(payload, query) {
2716
- const record = asRecord2(payload);
2530
+ const record = asRecord(payload);
2717
2531
  if (!record || !Array.isArray(record.data)) return payload;
2718
2532
  const filteredData = record.data.filter((row) => matchesSearchQuery(row, query));
2719
2533
  return {
@@ -3640,9 +3454,65 @@ var subitemUpdateContract = {
3640
3454
  rootKey: "subitem",
3641
3455
  fields: subitemFields
3642
3456
  };
3457
+ var reminderFields = {
3458
+ title: { type: "string", example: "Follow up with customer" },
3459
+ description: { type: "string" },
3460
+ due_at: { type: "string" },
3461
+ starts_at: { type: "string" },
3462
+ timezone: { type: "string", example: "America/Phoenix" },
3463
+ schedule: {
3464
+ type: "object",
3465
+ example: { type: "once", due_at: "2026-09-01T09:00:00-07:00" }
3466
+ },
3467
+ notification: {
3468
+ type: "object",
3469
+ example: { channels: ["in_app"], lead_minutes: 15 }
3470
+ },
3471
+ resources_attributes: { type: "array" },
3472
+ reminder_delegates_attributes: { type: "array" }
3473
+ };
3474
+ var reminderCreateContract = {
3475
+ rootKey: "reminder",
3476
+ fields: reminderFields,
3477
+ required: ["title", "schedule", "notification"],
3478
+ additionalProperties: false
3479
+ };
3480
+ var reminderUpdateContract = {
3481
+ rootKey: "reminder",
3482
+ fields: reminderFields,
3483
+ additionalProperties: false
3484
+ };
3485
+ var sketchFields = {
3486
+ name: { type: "string" },
3487
+ creation_key: { type: "string" },
3488
+ member_id: { type: "string" },
3489
+ teams_ids: { type: "array", items: { type: "string" } },
3490
+ status: {
3491
+ type: "string",
3492
+ enum: ["backlog", "planned", "in_progress", "completed", "cancelled", "ready_for_qa", "blocked"]
3493
+ },
3494
+ priority: { type: "string", enum: PRIORITIES }
3495
+ };
3496
+ var sketchCreateContract = {
3497
+ rootKey: "sketch",
3498
+ fields: sketchFields,
3499
+ required: ["name", "teams_ids", "creation_key"],
3500
+ additionalProperties: false
3501
+ };
3502
+ var sketchMetadataUpdateContract = {
3503
+ rootKey: "sketch",
3504
+ fields: Object.fromEntries(
3505
+ Object.entries(sketchFields).filter(([field]) => field !== "creation_key")
3506
+ ),
3507
+ additionalProperties: false
3508
+ };
3643
3509
  var CONTRACTS = {
3644
3510
  "list-items.create": listItemCreateContract,
3645
3511
  "list-items.update": listItemUpdateContract,
3512
+ "reminders.create": reminderCreateContract,
3513
+ "reminders.update": reminderUpdateContract,
3514
+ "sketches.create": sketchCreateContract,
3515
+ "sketches.update-metadata": sketchMetadataUpdateContract,
3646
3516
  "subitems.create": subitemCreateContract,
3647
3517
  "subitems.update": subitemUpdateContract
3648
3518
  };
@@ -3714,8 +3584,10 @@ function validateOperationDataJson(operationId2, value) {
3714
3584
  const missing = (contract.required ?? []).filter(
3715
3585
  (field) => entity[field] === void 0 || entity[field] === null || entity[field] === ""
3716
3586
  );
3587
+ const unsupported = contract.additionalProperties === false ? Object.keys(entity).filter((field) => !Object.prototype.hasOwnProperty.call(contract.fields, field)) : [];
3717
3588
  return [
3718
3589
  ...missing.map((field) => `${contract.rootKey}.${field} is required.`),
3590
+ ...unsupported.map((field) => `${contract.rootKey}.${field} is not permitted.`),
3719
3591
  ...validateFields(contract.fields, entity, [contract.rootKey])
3720
3592
  ].map(
3721
3593
  (error) => `Invalid input value for dataJson: ${error}`
@@ -3759,14 +3631,25 @@ function entitySchema(contract) {
3759
3631
  ])
3760
3632
  ),
3761
3633
  ...contract.required ? { required: [...contract.required] } : {},
3762
- additionalProperties: true
3634
+ additionalProperties: contract.additionalProperties ?? true
3763
3635
  };
3764
3636
  }
3637
+ function exampleValue2(contract) {
3638
+ if (contract.example !== void 0) return contract.example;
3639
+ if (contract.type === "array") return [];
3640
+ if (contract.type === "object") return {};
3641
+ if (contract.type === "number") return 0;
3642
+ if (contract.type === "boolean") return false;
3643
+ return "example";
3644
+ }
3765
3645
  function exampleDataJsonForOperation(operationId2) {
3766
3646
  const contract = CONTRACTS[operationId2];
3767
3647
  if (!contract) return null;
3768
3648
  const entity = Object.fromEntries(
3769
- (contract.required ?? []).map((field) => [field, "example"])
3649
+ (contract.required ?? []).map((field) => {
3650
+ const fieldContract = contract.fields[field];
3651
+ return [field, fieldContract ? exampleValue2(fieldContract) : "example"];
3652
+ })
3770
3653
  );
3771
3654
  return { [contract.rootKey]: entity };
3772
3655
  }
@@ -3872,7 +3755,7 @@ function registerEntityCrudCommands(program, config) {
3872
3755
  const entityCommand = program.command(config.command).description(config.description);
3873
3756
  const createHelp4 = buildDataJsonHelp(config.rootKey, "create") ?? "JSON object, optionally wrapped with root key";
3874
3757
  const updateHelp5 = buildDataJsonHelp(config.rootKey, "update") ?? "JSON object, optionally wrapped with root key";
3875
- const listField2 = config.listField ?? (config.resourcePath === "feedback" ? "feedbacks" : config.resourcePath);
3758
+ const listField2 = config.listField ?? config.resourcePath;
3876
3759
  const list = entityCommand.command("list").option("--page <page>").option("--per <per>");
3877
3760
  const listParams = config.listParams ?? [];
3878
3761
  const listParamHelp = config.listParamHelp ?? {};
@@ -3912,12 +3795,14 @@ function registerEntityCrudCommands(program, config) {
3912
3795
  isList: true
3913
3796
  });
3914
3797
  });
3915
- registerGraphqlSearchCommand(entityCommand, {
3916
- command: config.command,
3917
- field: listField2,
3918
- variableTypes: config.listVariableTypes,
3919
- selectionSet: config.listSelectionSet
3920
- });
3798
+ if (config.registerSearch !== false) {
3799
+ registerGraphqlSearchCommand(entityCommand, {
3800
+ command: config.command,
3801
+ field: listField2,
3802
+ variableTypes: config.listVariableTypes,
3803
+ selectionSet: config.listSelectionSet
3804
+ });
3805
+ }
3921
3806
  const show = entityCommand.command("show").requiredOption("--id <id>");
3922
3807
  showParams.forEach((param) => {
3923
3808
  const cliParam = param.replace(/_/g, "-");
@@ -3928,7 +3813,7 @@ function registerEntityCrudCommands(program, config) {
3928
3813
  const context = await resolveCommandContext(cmd.optsWithGlobals());
3929
3814
  const organizationId = resolveOrganizationId(context.organizationId);
3930
3815
  const defaultCommand = `${config.command}.show`;
3931
- const defaultField = config.showField ?? (config.resourcePath === "feedback" ? "feedback" : toSingularResourceName(config.resourcePath));
3816
+ const defaultField = config.showField ?? toSingularResourceName(config.resourcePath);
3932
3817
  const mappedShowParams = Object.fromEntries(
3933
3818
  showParams.map((param) => {
3934
3819
  const optionKey2 = param.replace(/_([a-z])/g, (_, char) => char.toUpperCase());
@@ -4012,6 +3897,22 @@ function registerEntityCrudCommands(program, config) {
4012
3897
  }
4013
3898
  });
4014
3899
  });
3900
+ for (const mutation of config.idMutationCommands ?? []) {
3901
+ entityCommand.command(mutation.command).description(mutation.description).requiredOption("--id <id>").action(async (opts, cmd) => {
3902
+ const id = idSchema2.parse(opts.id);
3903
+ const context = await resolveCommandContext(cmd.optsWithGlobals());
3904
+ const organizationId = resolveOrganizationId(context.organizationId);
3905
+ await runGraphqlMutationCommand({
3906
+ command: `${config.command}.${mutation.command}`,
3907
+ runtimeOptions: context.runtimeOptions,
3908
+ field: mutation.field,
3909
+ variables: {
3910
+ organization_id: organizationId,
3911
+ [mutation.idVariable]: id
3912
+ }
3913
+ });
3914
+ });
3915
+ }
4015
3916
  }
4016
3917
  var __testables = {
4017
3918
  toSingularResourceName,
@@ -4048,7 +3949,7 @@ var displayPreferenceAttributesSelectionSet = "attributes { id viewType favorite
4048
3949
  var filterPreferenceAttributesSelectionSet = "attributes { id filterType filter memberId focusMemberId focusTeamId filterableId filterableType preferenceType agendaItemId }";
4049
3950
  var healthUpdateSummarySelectionSet = "id type value memberId status createdAt updatedAt updatableType updatableId parentUpdateId emojis { id name memberId } resources { ...ResourceSummaryFull }";
4050
3951
  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 } }`;
4051
- function asRecord3(value) {
3952
+ function asRecord2(value) {
4052
3953
  return value && typeof value === "object" ? value : null;
4053
3954
  }
4054
3955
  function toNonEmptyString(value) {
@@ -4081,9 +3982,9 @@ function parseProjectPriority(value) {
4081
3982
  return parsed.data.toUpperCase();
4082
3983
  }
4083
3984
  function normalizeProjectRowForDisplay(row) {
4084
- const record = asRecord3(row);
3985
+ const record = asRecord2(row);
4085
3986
  if (!record) return row;
4086
- const attributes = asRecord3(record.attributes);
3987
+ const attributes = asRecord2(record.attributes);
4087
3988
  const topLevelName = toNonEmptyString(record.name);
4088
3989
  const topLevelTitle = toNonEmptyString(record.title);
4089
3990
  const attributeName = toNonEmptyString(attributes?.name);
@@ -4098,7 +3999,7 @@ function normalizeProjectRowForDisplay(row) {
4098
3999
  };
4099
4000
  }
4100
4001
  function normalizeProjectsListForDisplay(payload) {
4101
- const record = asRecord3(payload);
4002
+ const record = asRecord2(payload);
4102
4003
  if (!record || !Array.isArray(record.data)) return payload;
4103
4004
  return {
4104
4005
  ...record,
@@ -4316,7 +4217,7 @@ var MEETING_STATUSES = /* @__PURE__ */ new Set(["upcoming", "active", "completed
4316
4217
  var MEETING_REPEATS = /* @__PURE__ */ new Set(["never", "weekly", "biweekly", "monthly", "quarterly"]);
4317
4218
  var createHelp2 = buildDataJsonHelp("meeting", "create") ?? 'JSON object for meeting or {"meeting": {...}}';
4318
4219
  var updateHelp2 = buildDataJsonHelp("meeting", "update") ?? 'JSON object for meeting or {"meeting": {...}}';
4319
- function asNonEmptyString2(value) {
4220
+ function asNonEmptyString(value) {
4320
4221
  if (typeof value !== "string") {
4321
4222
  return void 0;
4322
4223
  }
@@ -4374,7 +4275,7 @@ function normalizeMeetingCreateBody(body) {
4374
4275
  });
4375
4276
  }
4376
4277
  const meeting = { ...entity };
4377
- const type = asNonEmptyString2(meeting.type);
4278
+ const type = asNonEmptyString(meeting.type);
4378
4279
  if (!type || !MEETING_TYPES.has(type)) {
4379
4280
  throw new CliError({
4380
4281
  message: "Invalid meeting.type. Use one of: TeamMeeting, OneOnOneMeeting.",
@@ -4384,8 +4285,8 @@ function normalizeMeetingCreateBody(body) {
4384
4285
  details: { field: "meeting.type", allowed: Array.from(MEETING_TYPES) }
4385
4286
  });
4386
4287
  }
4387
- const memberId = asNonEmptyString2(meeting.member_id);
4388
- const date = asNonEmptyString2(meeting.date);
4288
+ const memberId = asNonEmptyString(meeting.member_id);
4289
+ const date = asNonEmptyString(meeting.date);
4389
4290
  const startTime = toFiniteNumber(meeting.start_time, "meeting.start_time");
4390
4291
  const missingRequired = [];
4391
4292
  if (!memberId) missingRequired.push("member_id");
@@ -4400,7 +4301,7 @@ function normalizeMeetingCreateBody(body) {
4400
4301
  details: { requiredFields: ["member_id", "date", "start_time"], rootKey: "meeting" }
4401
4302
  });
4402
4303
  }
4403
- const status = asNonEmptyString2(meeting.status);
4304
+ const status = asNonEmptyString(meeting.status);
4404
4305
  if (status && !MEETING_STATUSES.has(status)) {
4405
4306
  throw new CliError({
4406
4307
  message: "Invalid meeting.status. Use one of: upcoming, active, completed.",
@@ -4410,7 +4311,7 @@ function normalizeMeetingCreateBody(body) {
4410
4311
  details: { field: "meeting.status", allowed: Array.from(MEETING_STATUSES) }
4411
4312
  });
4412
4313
  }
4413
- const repeats = asNonEmptyString2(meeting.repeats) ?? "never";
4314
+ const repeats = asNonEmptyString(meeting.repeats) ?? "never";
4414
4315
  if (!MEETING_REPEATS.has(repeats)) {
4415
4316
  throw new CliError({
4416
4317
  message: "Invalid meeting.repeats. Use one of: never, weekly, biweekly, monthly, quarterly.",
@@ -5139,13 +5040,35 @@ var SMART_KPI_NAMES = [
5139
5040
  var SMART_KPI_NAME_SET = new Set(SMART_KPI_NAMES);
5140
5041
 
5141
5042
  // src/commands/systemTools.ts
5043
+ var REMINDER_ATTRIBUTES_SELECTION = `
5044
+ id
5045
+ organizationId
5046
+ creatorId
5047
+ title
5048
+ description
5049
+ dueAt
5050
+ startsAt
5051
+ timezone
5052
+ schedule
5053
+ notification
5054
+ status
5055
+ nextTriggerAt
5056
+ lastTriggeredAt
5057
+ clearedAt
5058
+ reminderDelegates { id memberId organizationId }
5059
+ delegateMembers { id email firstName lastName organizationId }
5060
+ resources { id resourceType url creatorId attachment { id fileKey filename } }
5061
+ createdAt
5062
+ updatedAt
5063
+ `;
5064
+ var REMINDER_LIST_SELECTION = `{ data { id type attributes { ${REMINDER_ATTRIBUTES_SELECTION} } } count currentPage totalPages }`;
5065
+ var REMINDER_SHOW_SELECTION = `{ id type attributes { ${REMINDER_ATTRIBUTES_SELECTION} } }`;
5142
5066
  var TODO_STATUSES = /* @__PURE__ */ new Set(["open", "completed"]);
5143
5067
  var KNOWLEDGE_CONTENT_TYPES = /* @__PURE__ */ new Set(["company", "policy", "process"]);
5144
5068
  var KNOWLEDGE_STATUSES = /* @__PURE__ */ new Set(["draft", "published"]);
5145
5069
  var NEWS_STATUSES = /* @__PURE__ */ new Set(["active", "completed"]);
5146
5070
  var NEWS_HEADLINE_TYPES = /* @__PURE__ */ new Set(["team", "org_wide"]);
5147
5071
  var QUESTION_STATUSES = /* @__PURE__ */ new Set(["asked", "answered"]);
5148
- var PULSE_STATUSES = /* @__PURE__ */ new Set(["on_track", "at_risk", "off_track"]);
5149
5072
  var SURVEY_RECIPIENT_TYPES = /* @__PURE__ */ new Set(["member", "team", "org_wide"]);
5150
5073
  var SURVEY_NAMES = /* @__PURE__ */ new Set([
5151
5074
  "employee_net_promoter_score",
@@ -5158,21 +5081,6 @@ var SURVEY_NAMES = /* @__PURE__ */ new Set([
5158
5081
  "manager_review",
5159
5082
  "onboarding"
5160
5083
  ]);
5161
- var FEEDBACK_QUARTERS = /* @__PURE__ */ new Set(["q1", "q2", "q3", "q4"]);
5162
- var FEEDBACK_NAMES = /* @__PURE__ */ new Set([
5163
- "productivity_and_focus",
5164
- "company_collaboration",
5165
- "project_management",
5166
- "employee_engagement",
5167
- "training_and_development",
5168
- "innovation_and_creativity",
5169
- "customer_insights",
5170
- "process_improvement",
5171
- "leadership_and_management",
5172
- "company_culture",
5173
- "roadmap_and_strategy",
5174
- "customer_testing_and_feedback"
5175
- ]);
5176
5084
  var SCORECARD_INTERVALS = /* @__PURE__ */ new Set([
5177
5085
  "daily",
5178
5086
  "weekly",
@@ -5223,7 +5131,7 @@ function normalizeTodosCreateBody(body) {
5223
5131
  }
5224
5132
  return { ...body, todo };
5225
5133
  }
5226
- function asNonEmptyString3(value) {
5134
+ function asNonEmptyString2(value) {
5227
5135
  if (typeof value !== "string") {
5228
5136
  return void 0;
5229
5137
  }
@@ -5231,7 +5139,7 @@ function asNonEmptyString3(value) {
5231
5139
  return trimmed.length > 0 ? trimmed : void 0;
5232
5140
  }
5233
5141
  function validateEnumField(params) {
5234
- const value = asNonEmptyString3(params.rawValue);
5142
+ const value = asNonEmptyString2(params.rawValue);
5235
5143
  if (!value) {
5236
5144
  return void 0;
5237
5145
  }
@@ -5265,7 +5173,7 @@ function normalizeKnowledgeCreateBody(body) {
5265
5173
  message: "Invalid content.status. Use one of: draft, published."
5266
5174
  });
5267
5175
  content.status = status ?? "draft";
5268
- const memberId = asNonEmptyString3(content.member_id);
5176
+ const memberId = asNonEmptyString2(content.member_id);
5269
5177
  if (!memberId) {
5270
5178
  throwMissingRequiredCreateFields("content", ["member_id"]);
5271
5179
  }
@@ -5274,7 +5182,7 @@ function normalizeKnowledgeCreateBody(body) {
5274
5182
  }
5275
5183
  function normalizeNewsCreateBody(body) {
5276
5184
  const headline = ensureEntityObject(body, "headline");
5277
- const memberId = asNonEmptyString3(headline.member_id);
5185
+ const memberId = asNonEmptyString2(headline.member_id);
5278
5186
  if (!memberId) {
5279
5187
  throwMissingRequiredCreateFields("headline", ["member_id"]);
5280
5188
  }
@@ -5303,14 +5211,14 @@ function normalizeNewsCreateBody(body) {
5303
5211
  }
5304
5212
  function normalizeQuestionsCreateBody(body) {
5305
5213
  const question = ensureEntityObject(body, "question");
5306
- const summary = asNonEmptyString3(question.summary);
5307
- const currentName = asNonEmptyString3(question.name);
5214
+ const summary = asNonEmptyString2(question.summary);
5215
+ const currentName = asNonEmptyString2(question.name);
5308
5216
  if (!currentName && summary) {
5309
5217
  question.name = summary;
5310
5218
  }
5311
5219
  delete question.summary;
5312
- const name = asNonEmptyString3(question.name);
5313
- const memberId = asNonEmptyString3(question.member_id);
5220
+ const name = asNonEmptyString2(question.name);
5221
+ const memberId = asNonEmptyString2(question.member_id);
5314
5222
  const missing = [];
5315
5223
  if (!name) missing.push("name");
5316
5224
  if (!memberId) missing.push("member_id");
@@ -5332,13 +5240,13 @@ function normalizeQuestionsCreateBody(body) {
5332
5240
  }
5333
5241
  function normalizeQuestionsUpdateBody(body) {
5334
5242
  const question = ensureEntityObject(body, "question");
5335
- const summary = asNonEmptyString3(question.summary);
5336
- const currentName = asNonEmptyString3(question.name);
5243
+ const summary = asNonEmptyString2(question.summary);
5244
+ const currentName = asNonEmptyString2(question.name);
5337
5245
  if (!currentName && summary) {
5338
5246
  question.name = summary;
5339
5247
  }
5340
5248
  delete question.summary;
5341
- const name = asNonEmptyString3(question.name);
5249
+ const name = asNonEmptyString2(question.name);
5342
5250
  if (name) {
5343
5251
  question.name = name;
5344
5252
  }
@@ -5353,37 +5261,10 @@ function normalizeQuestionsUpdateBody(body) {
5353
5261
  }
5354
5262
  return { ...body, question };
5355
5263
  }
5356
- function normalizePulseCreateBody(body) {
5357
- const healthUpdate = ensureEntityObject(body, "health_update");
5358
- const healthUpdatableId = asNonEmptyString3(healthUpdate.health_updatable_id) ?? asNonEmptyString3(healthUpdate.updatable_id);
5359
- const healthUpdatableType = asNonEmptyString3(healthUpdate.health_updatable_type) ?? asNonEmptyString3(healthUpdate.updatable_type);
5360
- const memberId = asNonEmptyString3(healthUpdate.member_id);
5361
- const status = validateEnumField({
5362
- rawValue: healthUpdate.status,
5363
- field: "health_update.status",
5364
- allowed: PULSE_STATUSES,
5365
- message: "Invalid health_update.status. Use one of: on_track, at_risk, off_track."
5366
- });
5367
- const missing = [];
5368
- if (!healthUpdatableId) missing.push("health_updatable_id");
5369
- if (!healthUpdatableType) missing.push("health_updatable_type");
5370
- if (!memberId) missing.push("member_id");
5371
- if (!status) missing.push("status");
5372
- if (missing.length > 0) {
5373
- throwMissingRequiredCreateFields("health_update", missing);
5374
- }
5375
- healthUpdate.health_updatable_id = healthUpdatableId;
5376
- healthUpdate.health_updatable_type = healthUpdatableType;
5377
- healthUpdate.member_id = memberId;
5378
- healthUpdate.status = status;
5379
- delete healthUpdate.updatable_id;
5380
- delete healthUpdate.updatable_type;
5381
- return { ...body, health_update: healthUpdate };
5382
- }
5383
5264
  function normalizeSurveysCreateBody(body) {
5384
5265
  const survey = ensureEntityObject(body, "survey");
5385
- const title = asNonEmptyString3(survey.title);
5386
- const currentName = asNonEmptyString3(survey.name);
5266
+ const title = asNonEmptyString2(survey.title);
5267
+ const currentName = asNonEmptyString2(survey.name);
5387
5268
  if (!currentName && title) {
5388
5269
  survey.name = title;
5389
5270
  }
@@ -5412,8 +5293,8 @@ function normalizeSurveysCreateBody(body) {
5412
5293
  }
5413
5294
  function normalizeSurveysUpdateBody(body) {
5414
5295
  const survey = ensureEntityObject(body, "survey");
5415
- const title = asNonEmptyString3(survey.title);
5416
- const currentName = asNonEmptyString3(survey.name);
5296
+ const title = asNonEmptyString2(survey.title);
5297
+ const currentName = asNonEmptyString2(survey.name);
5417
5298
  if (!currentName && title) {
5418
5299
  survey.name = title;
5419
5300
  }
@@ -5438,77 +5319,16 @@ function normalizeSurveysUpdateBody(body) {
5438
5319
  }
5439
5320
  return { ...body, survey };
5440
5321
  }
5441
- function normalizeFeedbacksCreateBody(body) {
5442
- const feedback = ensureEntityObject(body, "feedback");
5443
- const title = asNonEmptyString3(feedback.title);
5444
- const currentName = asNonEmptyString3(feedback.name);
5445
- if (!currentName && title) {
5446
- feedback.name = title;
5447
- }
5448
- delete feedback.title;
5449
- const name = validateEnumField({
5450
- rawValue: feedback.name,
5451
- field: "feedback.name",
5452
- allowed: FEEDBACK_NAMES,
5453
- message: "Invalid feedback.name. Use one of: productivity_and_focus, company_collaboration, project_management, employee_engagement, training_and_development, innovation_and_creativity, customer_insights, process_improvement, leadership_and_management, company_culture, roadmap_and_strategy, customer_testing_and_feedback."
5454
- });
5455
- const quarter = validateEnumField({
5456
- rawValue: feedback.quarter,
5457
- field: "feedback.quarter",
5458
- allowed: FEEDBACK_QUARTERS,
5459
- message: "Invalid feedback.quarter. Use one of: q1, q2, q3, q4."
5460
- });
5461
- const year = asNonEmptyString3(feedback.year);
5462
- const missing = [];
5463
- if (!name) missing.push("name");
5464
- if (!quarter) missing.push("quarter");
5465
- if (!year) missing.push("year");
5466
- if (missing.length > 0) {
5467
- throwMissingRequiredCreateFields("feedback", missing);
5468
- }
5469
- feedback.name = name;
5470
- feedback.quarter = quarter;
5471
- feedback.year = year;
5472
- return { ...body, feedback };
5473
- }
5474
- function normalizeFeedbacksUpdateBody(body) {
5475
- const feedback = ensureEntityObject(body, "feedback");
5476
- const title = asNonEmptyString3(feedback.title);
5477
- const currentName = asNonEmptyString3(feedback.name);
5478
- if (!currentName && title) {
5479
- feedback.name = title;
5480
- }
5481
- delete feedback.title;
5482
- const name = validateEnumField({
5483
- rawValue: feedback.name,
5484
- field: "feedback.name",
5485
- allowed: FEEDBACK_NAMES,
5486
- message: "Invalid feedback.name. Use one of: productivity_and_focus, company_collaboration, project_management, employee_engagement, training_and_development, innovation_and_creativity, customer_insights, process_improvement, leadership_and_management, company_culture, roadmap_and_strategy, customer_testing_and_feedback."
5487
- });
5488
- if (name) {
5489
- feedback.name = name;
5490
- }
5491
- const quarter = validateEnumField({
5492
- rawValue: feedback.quarter,
5493
- field: "feedback.quarter",
5494
- allowed: FEEDBACK_QUARTERS,
5495
- message: "Invalid feedback.quarter. Use one of: q1, q2, q3, q4."
5496
- });
5497
- if (quarter) {
5498
- feedback.quarter = quarter;
5499
- }
5500
- return { ...body, feedback };
5501
- }
5502
5322
  function normalizeAccountabilityCreateBody(body) {
5503
5323
  const responsibility = ensureEntityObject(body, "responsibility");
5504
- const summary = asNonEmptyString3(responsibility.summary);
5505
- const currentName = asNonEmptyString3(responsibility.name);
5324
+ const summary = asNonEmptyString2(responsibility.summary);
5325
+ const currentName = asNonEmptyString2(responsibility.name);
5506
5326
  if (!currentName && summary) {
5507
5327
  responsibility.name = summary;
5508
5328
  }
5509
5329
  delete responsibility.summary;
5510
- const name = asNonEmptyString3(responsibility.name);
5511
- const memberId = asNonEmptyString3(responsibility.member_id);
5330
+ const name = asNonEmptyString2(responsibility.name);
5331
+ const memberId = asNonEmptyString2(responsibility.member_id);
5512
5332
  const missing = [];
5513
5333
  if (!name) missing.push("name");
5514
5334
  if (!memberId) missing.push("member_id");
@@ -5523,8 +5343,8 @@ function normalizeAccountabilityCreateBody(body) {
5523
5343
  }
5524
5344
  function normalizeAccountabilityUpdateBody(body) {
5525
5345
  const responsibility = ensureEntityObject(body, "responsibility");
5526
- const summary = asNonEmptyString3(responsibility.summary);
5527
- const currentName = asNonEmptyString3(responsibility.name);
5346
+ const summary = asNonEmptyString2(responsibility.summary);
5347
+ const currentName = asNonEmptyString2(responsibility.name);
5528
5348
  if (!currentName && summary) {
5529
5349
  responsibility.name = summary;
5530
5350
  }
@@ -5556,7 +5376,7 @@ function parseSmartKpiViewCreateBody(raw) {
5556
5376
  }
5557
5377
  function normalizeSmartKpiViewCreateBody(body) {
5558
5378
  const smartKpiView = ensureEntityObject(body, "smart_kpi_view");
5559
- const name = asNonEmptyString3(smartKpiView.name);
5379
+ const name = asNonEmptyString2(smartKpiView.name);
5560
5380
  if (!name) {
5561
5381
  throwMissingRequiredCreateFields("smart_kpi_view", ["name"]);
5562
5382
  }
@@ -5594,9 +5414,9 @@ function buildKpisCreateMutation(params) {
5594
5414
  });
5595
5415
  }
5596
5416
  const smartKpi = { ...entity };
5597
- const name = asNonEmptyString3(smartKpi.name);
5598
- const smartKpiViewId = asNonEmptyString3(smartKpi.smart_kpi_view_id);
5599
- const measurableGroupId = asNonEmptyString3(smartKpi.measurable_group_id);
5417
+ const name = asNonEmptyString2(smartKpi.name);
5418
+ const smartKpiViewId = asNonEmptyString2(smartKpi.smart_kpi_view_id);
5419
+ const measurableGroupId = asNonEmptyString2(smartKpi.measurable_group_id);
5600
5420
  const hasAllowedName = typeof name === "string" && SMART_KPI_NAME_SET.has(name);
5601
5421
  if (!name) {
5602
5422
  throw new CliError({
@@ -5616,7 +5436,7 @@ function buildKpisCreateMutation(params) {
5616
5436
  measurable_type: "number",
5617
5437
  condition: "greater_than_or_equal_to"
5618
5438
  };
5619
- const notes = asNonEmptyString3(smartKpi.notes);
5439
+ const notes = asNonEmptyString2(smartKpi.notes);
5620
5440
  if (notes) {
5621
5441
  measurable.notes = notes;
5622
5442
  }
@@ -5685,6 +5505,32 @@ function registerSmartKpiViewCommands(program) {
5685
5505
  });
5686
5506
  }
5687
5507
  function registerSystemToolCommands(program) {
5508
+ registerEntityCrudCommands(program, {
5509
+ command: "reminders",
5510
+ description: "Reminder operations",
5511
+ resourcePath: "reminders",
5512
+ rootKey: "reminder",
5513
+ requiredCreateFields: ["title"],
5514
+ listParams: ["status", "sort"],
5515
+ allowQueryJson: false,
5516
+ registerSearch: false,
5517
+ listSelectionSet: REMINDER_LIST_SELECTION,
5518
+ showSelectionSet: REMINDER_SHOW_SELECTION,
5519
+ idMutationCommands: [
5520
+ {
5521
+ command: "clear",
5522
+ description: "Clear a reminder while retaining its history",
5523
+ field: "clear_reminder",
5524
+ idVariable: "reminder_id"
5525
+ },
5526
+ {
5527
+ command: "destroy",
5528
+ description: "Cancel a reminder while retaining its history",
5529
+ field: "destroy_reminder",
5530
+ idVariable: "reminder_id"
5531
+ }
5532
+ ]
5533
+ });
5688
5534
  registerEntityCrudCommands(program, {
5689
5535
  command: "lists",
5690
5536
  description: "List operations",
@@ -5829,18 +5675,6 @@ function registerSystemToolCommands(program) {
5829
5675
  listParams: ["answered", "asked"],
5830
5676
  allowQueryJson: false
5831
5677
  });
5832
- registerEntityCrudCommands(program, {
5833
- command: "pulse",
5834
- description: "Pulse operations",
5835
- resourcePath: "health_updates",
5836
- rootKey: "health_update",
5837
- listField: "feedbacks",
5838
- showField: "feedback",
5839
- requiredCreateFields: ["health_updatable_id", "health_updatable_type", "member_id", "status"],
5840
- normalizeCreateBody: normalizePulseCreateBody,
5841
- listParams: ["last", "latest", "start_date", "name", "quarter", "year"],
5842
- allowQueryJson: false
5843
- });
5844
5678
  registerEntityCrudCommands(program, {
5845
5679
  command: "surveys",
5846
5680
  description: "Survey operations",
@@ -5852,17 +5686,6 @@ function registerSystemToolCommands(program) {
5852
5686
  listParams: ["completed", "current_member", "due", "exclude_completed", "sent"],
5853
5687
  allowQueryJson: false
5854
5688
  });
5855
- registerEntityCrudCommands(program, {
5856
- command: "feedbacks",
5857
- description: "Feedback operations",
5858
- resourcePath: "feedback",
5859
- rootKey: "feedback",
5860
- requiredCreateFields: ["name", "quarter", "year"],
5861
- normalizeCreateBody: normalizeFeedbacksCreateBody,
5862
- normalizeUpdateBody: normalizeFeedbacksUpdateBody,
5863
- listParams: ["last", "latest", "start_date"],
5864
- allowQueryJson: false
5865
- });
5866
5689
  registerEntityCrudCommands(program, {
5867
5690
  command: "accountability",
5868
5691
  description: "Accountability operations",
@@ -6019,7 +5842,7 @@ function ensureRootObject(body, rootKey) {
6019
5842
  }
6020
5843
  return { ...root };
6021
5844
  }
6022
- function asNonEmptyString4(value) {
5845
+ function asNonEmptyString3(value) {
6023
5846
  if (typeof value !== "string") {
6024
5847
  return void 0;
6025
5848
  }
@@ -6029,7 +5852,7 @@ function asNonEmptyString4(value) {
6029
5852
  function normalizeOrganizationUpdateBody(body) {
6030
5853
  const organization = ensureRootObject(body, "organization");
6031
5854
  const detail = isRecord3(organization.organization_detail_attributes) ? { ...organization.organization_detail_attributes } : {};
6032
- const workspaceName = asNonEmptyString4(organization.workspace_name);
5855
+ const workspaceName = asNonEmptyString3(organization.workspace_name);
6033
5856
  if (workspaceName) {
6034
5857
  detail.workspace_name = workspaceName;
6035
5858
  }
@@ -6042,7 +5865,7 @@ function normalizeOrganizationUpdateBody(body) {
6042
5865
  function normalizeOrganizationMetaProfileUpdateBody(body) {
6043
5866
  const root = ensureRootObject(body, "organization_meta_profile");
6044
5867
  const profile = isRecord3(root.profile) ? { ...root.profile } : {};
6045
- const title = asNonEmptyString4(root.title);
5868
+ const title = asNonEmptyString3(root.title);
6046
5869
  if (title) {
6047
5870
  const companyIdentity = isRecord3(profile.company_identity) ? { ...profile.company_identity } : {};
6048
5871
  companyIdentity.one_sentence_summary = title;
@@ -6072,7 +5895,7 @@ function normalizeOrganizationMetaProfileUpdateBody(body) {
6072
5895
  function normalizeKeyMetricMetaProfileUpdateBody(body) {
6073
5896
  const root = ensureRootObject(body, "key_metric_meta_profile");
6074
5897
  const profile = isRecord3(root.profile) ? { ...root.profile } : {};
6075
- const annualRevenue = asNonEmptyString4(root.annual_revenue);
5898
+ const annualRevenue = asNonEmptyString3(root.annual_revenue);
6076
5899
  if (annualRevenue) {
6077
5900
  const financial = isRecord3(profile.financial) ? { ...profile.financial } : {};
6078
5901
  financial.revenue = annualRevenue;
@@ -6256,7 +6079,7 @@ function ensureRootObject2(body, rootKey) {
6256
6079
  }
6257
6080
  return { ...root };
6258
6081
  }
6259
- function asNonEmptyString5(value) {
6082
+ function asNonEmptyString4(value) {
6260
6083
  if (typeof value !== "string") {
6261
6084
  return void 0;
6262
6085
  }
@@ -6284,8 +6107,8 @@ function normalizeStrategicPlanUpdateBody(body) {
6284
6107
  }
6285
6108
  function normalizeStrategicObjectiveUpdateBody(body) {
6286
6109
  const strategicObjective = ensureRootObject2(body, "strategic_objective");
6287
- const title = asNonEmptyString5(strategicObjective.title);
6288
- if (!asNonEmptyString5(strategicObjective.summary) && title) {
6110
+ const title = asNonEmptyString4(strategicObjective.title);
6111
+ if (!asNonEmptyString4(strategicObjective.summary) && title) {
6289
6112
  strategicObjective.summary = title;
6290
6113
  }
6291
6114
  delete strategicObjective.title;
@@ -6308,8 +6131,8 @@ function normalizeStrategicObjectiveUpdateBody(body) {
6308
6131
  }
6309
6132
  function normalizeAnnualObjectiveCreateBody(body) {
6310
6133
  const annualObjective = ensureRootObject2(body, "annual_objective");
6311
- const title = asNonEmptyString5(annualObjective.title);
6312
- if (!asNonEmptyString5(annualObjective.name) && title) {
6134
+ const title = asNonEmptyString4(annualObjective.title);
6135
+ if (!asNonEmptyString4(annualObjective.name) && title) {
6313
6136
  annualObjective.name = title;
6314
6137
  }
6315
6138
  delete annualObjective.title;
@@ -6317,8 +6140,8 @@ function normalizeAnnualObjectiveCreateBody(body) {
6317
6140
  }
6318
6141
  function normalizeQuarterlyObjectiveCreateBody(body) {
6319
6142
  const quarterlyObjective = ensureRootObject2(body, "quarterly_objective");
6320
- const title = asNonEmptyString5(quarterlyObjective.title);
6321
- if (!asNonEmptyString5(quarterlyObjective.name) && title) {
6143
+ const title = asNonEmptyString4(quarterlyObjective.title);
6144
+ if (!asNonEmptyString4(quarterlyObjective.name) && title) {
6322
6145
  quarterlyObjective.name = title;
6323
6146
  }
6324
6147
  delete quarterlyObjective.title;
@@ -6461,7 +6284,18 @@ function requiredParentSearchOption(parentFlag, parentKind) {
6461
6284
  }
6462
6285
  function buildChildResourceSelectionSet(parentField, extraFields = []) {
6463
6286
  const fields = Array.from(
6464
- /* @__PURE__ */ new Set(["id", "type", "name", "status", "priority", "rank", "dueDate", "memberId", parentField, ...extraFields])
6287
+ /* @__PURE__ */ new Set([
6288
+ "id",
6289
+ "type",
6290
+ "name",
6291
+ "status",
6292
+ "priority",
6293
+ "rank",
6294
+ "dueDate",
6295
+ "memberId",
6296
+ parentField,
6297
+ ...extraFields
6298
+ ])
6465
6299
  );
6466
6300
  const attributeFields = fields.filter((field) => field !== "type");
6467
6301
  return `{ ${fields.join(" ")} attributes { ${attributeFields.join(" ")} } }`;
@@ -6469,6 +6303,30 @@ function buildChildResourceSelectionSet(parentField, extraFields = []) {
6469
6303
  function buildChildListSelectionSet(parentField, extraFields = []) {
6470
6304
  return `{ data ${buildChildResourceSelectionSet(parentField, extraFields)} count currentPage totalPages }`;
6471
6305
  }
6306
+ function buildChildShowSelectionSet(parentField, extraFields = []) {
6307
+ const fields = Array.from(
6308
+ /* @__PURE__ */ new Set([
6309
+ "id",
6310
+ "type",
6311
+ "name",
6312
+ "status",
6313
+ "priority",
6314
+ "rank",
6315
+ "dueDate",
6316
+ "memberId",
6317
+ parentField,
6318
+ "notes",
6319
+ "hasNotes",
6320
+ "hasUnreadNotes",
6321
+ "notesUpdatedAt",
6322
+ "notesLastReadAt",
6323
+ "estimateIds",
6324
+ ...extraFields
6325
+ ])
6326
+ );
6327
+ const attributeFields = fields.filter((field) => field !== "type");
6328
+ return `{ ${fields.join(" ")} attributes { ${attributeFields.join(" ")} } }`;
6329
+ }
6472
6330
  function parseJsonObject2(raw) {
6473
6331
  try {
6474
6332
  const parsed = JSON.parse(raw);
@@ -6846,11 +6704,14 @@ function registerChildEntityCommands(program) {
6846
6704
  updateField: "update_talking_point",
6847
6705
  destroyField: "destroy_talking_point",
6848
6706
  idVariable: "talking_point_id",
6707
+ showField: "talking_point",
6849
6708
  listOperationName: "TalkingPointsList",
6709
+ showOperationName: "TalkingPointsShow",
6850
6710
  createOperationName: "TalkingPointsCreate",
6851
6711
  updateOperationName: "TalkingPointsUpdate",
6852
6712
  destroyOperationName: "TalkingPointsDestroy",
6853
6713
  listSelectionSet: buildChildListSelectionSet("meetingId", ["description", "creatorId", "slug"]),
6714
+ showSelectionSet: buildChildShowSelectionSet("meetingId", ["description", "creatorId", "slug"]),
6854
6715
  listParentTypedField: "meetingId"
6855
6716
  });
6856
6717
  }
@@ -7217,7 +7078,7 @@ var import_zod18 = require("zod");
7217
7078
 
7218
7079
  // src/internalOptions.ts
7219
7080
  var INTERNAL_OPTIONS_KEY = "__waveInternalOptions";
7220
- function asRecord4(value) {
7081
+ function asRecord3(value) {
7221
7082
  if (!value || typeof value !== "object" || Array.isArray(value)) {
7222
7083
  return null;
7223
7084
  }
@@ -7231,7 +7092,7 @@ function setInternalCliOptions(program, options) {
7231
7092
  function getInternalCliOptions(command) {
7232
7093
  let current = command;
7233
7094
  while (current) {
7234
- const record = asRecord4(current[INTERNAL_OPTIONS_KEY]);
7095
+ const record = asRecord3(current[INTERNAL_OPTIONS_KEY]);
7235
7096
  if (record) {
7236
7097
  return {
7237
7098
  enableRetryOnEmptyPhrase: record.enableRetryOnEmptyPhrase === true
@@ -8034,7 +7895,7 @@ var import_commander = require("commander");
8034
7895
  var import_node_crypto3 = require("crypto");
8035
7896
 
8036
7897
  // src/version.ts
8037
- var CLI_VERSION = "0.1.87";
7898
+ var CLI_VERSION = "0.1.88";
8038
7899
 
8039
7900
  // src/operationMetadata.ts
8040
7901
  var DISCOVERY_OPERATION_IDS = [
@@ -8070,8 +7931,6 @@ var DISCOVERY_OPERATION_IDS = [
8070
7931
  "doctor",
8071
7932
  "doctor.examples",
8072
7933
  "doctor.schema",
8073
- "feedbacks.examples",
8074
- "feedbacks.schema",
8075
7934
  "foundation.examples",
8076
7935
  "foundation.schema",
8077
7936
  "issue-groups.examples",
@@ -8108,8 +7967,6 @@ var DISCOVERY_OPERATION_IDS = [
8108
7967
  "project-content.schema",
8109
7968
  "projects.examples",
8110
7969
  "projects.schema",
8111
- "pulse.examples",
8112
- "pulse.schema",
8113
7970
  "questions.examples",
8114
7971
  "questions.schema",
8115
7972
  "recognition.examples",
@@ -8151,7 +8008,9 @@ var DISCOVERY_OPERATION_IDS = [
8151
8008
  "todos.examples",
8152
8009
  "todos.schema",
8153
8010
  "whiteboards.examples",
8154
- "whiteboards.schema"
8011
+ "whiteboards.schema",
8012
+ "sketches.examples",
8013
+ "sketches.schema"
8155
8014
  ];
8156
8015
  var READ_OPERATION_IDS = [
8157
8016
  "accountability.list",
@@ -8188,9 +8047,6 @@ var READ_OPERATION_IDS = [
8188
8047
  "desktop-context.member-statuses",
8189
8048
  "desktop-context.recent",
8190
8049
  "desktop-context.status",
8191
- "feedbacks.list",
8192
- "feedbacks.search",
8193
- "feedbacks.show",
8194
8050
  "find",
8195
8051
  "foundation.annual-objectives.list",
8196
8052
  "foundation.annual-objectives.search",
@@ -8226,6 +8082,7 @@ var READ_OPERATION_IDS = [
8226
8082
  "mail.message",
8227
8083
  "mail.messages",
8228
8084
  "mail.open",
8085
+ "mail.relay-evidence",
8229
8086
  "mail.settings",
8230
8087
  "mail.snippets",
8231
8088
  "mail.sync-status",
@@ -8290,9 +8147,6 @@ var READ_OPERATION_IDS = [
8290
8147
  "projects.list",
8291
8148
  "projects.search",
8292
8149
  "projects.show",
8293
- "pulse.list",
8294
- "pulse.search",
8295
- "pulse.show",
8296
8150
  "questions.list",
8297
8151
  "questions.search",
8298
8152
  "questions.show",
@@ -8304,6 +8158,8 @@ var READ_OPERATION_IDS = [
8304
8158
  "rock-collections.list",
8305
8159
  "rock-collections.search",
8306
8160
  "rock-collections.show",
8161
+ "reminders.list",
8162
+ "reminders.show",
8307
8163
  "rocks.list",
8308
8164
  "rocks.search",
8309
8165
  "rocks.show",
@@ -8316,6 +8172,8 @@ var READ_OPERATION_IDS = [
8316
8172
  "skills.list",
8317
8173
  "skills.show",
8318
8174
  "stand-ups.list",
8175
+ "signatures.list",
8176
+ "signatures.show",
8319
8177
  "stand-ups.search",
8320
8178
  "stand-ups.show",
8321
8179
  "subissues.list",
@@ -8339,13 +8197,12 @@ var READ_OPERATION_IDS = [
8339
8197
  "support.settings",
8340
8198
  "support.ticket-counts",
8341
8199
  "support.tickets",
8342
- "signatures.list",
8343
- "signatures.show",
8344
8200
  "surveys.list",
8345
8201
  "surveys.search",
8346
8202
  "surveys.show",
8347
8203
  "talking-points.list",
8348
8204
  "talking-points.search",
8205
+ "talking-points.show",
8349
8206
  "tasks.list",
8350
8207
  "tasks.search",
8351
8208
  "tasks.show",
@@ -8367,7 +8224,10 @@ var READ_OPERATION_IDS = [
8367
8224
  "tree",
8368
8225
  "whiteboards.list",
8369
8226
  "whiteboards.open",
8370
- "whiteboards.show"
8227
+ "whiteboards.show",
8228
+ "sketches.list",
8229
+ "sketches.open",
8230
+ "sketches.show"
8371
8231
  ];
8372
8232
  var WRITE_OPERATION_IDS = [
8373
8233
  "accountability.create",
@@ -8418,8 +8278,6 @@ var WRITE_OPERATION_IDS = [
8418
8278
  "datasheets.view.delete",
8419
8279
  "datasheets.view.reorder",
8420
8280
  "datasheets.view.update",
8421
- "feedbacks.create",
8422
- "feedbacks.update",
8423
8281
  "foundation.annual-objectives.create",
8424
8282
  "foundation.annual-objectives.update",
8425
8283
  "foundation.quarterly-objectives.create",
@@ -8467,8 +8325,6 @@ var WRITE_OPERATION_IDS = [
8467
8325
  "project-content.update",
8468
8326
  "projects.create",
8469
8327
  "projects.update",
8470
- "pulse.create",
8471
- "pulse.update",
8472
8328
  "questions.create",
8473
8329
  "questions.update",
8474
8330
  "rock-collections.create",
@@ -8476,6 +8332,10 @@ var WRITE_OPERATION_IDS = [
8476
8332
  "rocks.create",
8477
8333
  "rocks.update",
8478
8334
  "rocks.update-status",
8335
+ "reminders.clear",
8336
+ "reminders.create",
8337
+ "reminders.destroy",
8338
+ "reminders.update",
8479
8339
  "scorecard-groups.create",
8480
8340
  "scorecard-groups.update",
8481
8341
  "scorecards.create",
@@ -8517,7 +8377,9 @@ var WRITE_OPERATION_IDS = [
8517
8377
  "todo-groups.create",
8518
8378
  "todo-groups.update",
8519
8379
  "todos.create",
8520
- "todos.update"
8380
+ "todos.update",
8381
+ "sketches.create",
8382
+ "sketches.update-metadata"
8521
8383
  ];
8522
8384
  var DIRECT_MACHINE_WRITE_OPERATION_IDS = /* @__PURE__ */ new Set(["automations.create"]);
8523
8385
  var AUTH_OPERATION_IDS = ["login", "logout"];
@@ -8538,6 +8400,8 @@ var DESTRUCTIVE_OPERATION_IDS = /* @__PURE__ */ new Set([
8538
8400
  "datasheets.view.delete",
8539
8401
  "milestones.destroy",
8540
8402
  "project-content.destroy",
8403
+ "reminders.clear",
8404
+ "reminders.destroy",
8541
8405
  "signatures.destroy",
8542
8406
  "signatures.void",
8543
8407
  "subissues.destroy",
@@ -9835,15 +9699,15 @@ function normalizeAgentFilePath(file, parentRef) {
9835
9699
  const trimmed = nonEmptyString3.parse(file).trim().replace(/^\/+|\/+$/g, "");
9836
9700
  const fileName = trimmed.startsWith(".agent/") ? trimmed.slice(".agent/".length) : trimmed;
9837
9701
  const isThreadWorkspace = atlasThreadWorkspaceParentRefPattern.test(parentRef);
9838
- const isSupportedFile = isThreadWorkspace ? /^[a-z0-9][a-z0-9-]*\.(?:md|txt)$/.test(fileName) : isSupportedAgentOverlayFileName(fileName);
9702
+ const isSupportedFile = isThreadWorkspace ? /^[a-z0-9][a-z0-9-]*\.(?:md|txt|csv)$/.test(fileName) : isSupportedAgentOverlayFileName(fileName);
9839
9703
  if (fileName.includes("\\") || fileName.includes("/") || fileName === "." || fileName === ".." || !isSupportedFile) {
9840
9704
  throw new CliError({
9841
- message: isThreadWorkspace ? "Atlas task workspaces support only lowercase kebab-case .md or .txt basenames." : ".agent supports only notes.md, summary.md, or <lowercase-kebab-slug>.md.",
9705
+ message: isThreadWorkspace ? "Atlas task workspaces support only lowercase kebab-case .md, .txt, or .csv basenames." : ".agent supports only notes.md, summary.md, or <lowercase-kebab-slug>.md.",
9842
9706
  kind: "invalid_args",
9843
9707
  status: 400,
9844
9708
  exitCode: EXIT_CODES.invalidArgs,
9845
9709
  details: {
9846
- supportedFiles: isThreadWorkspace ? ["<lowercase-kebab-slug>.md", "<lowercase-kebab-slug>.txt"] : [...supportedAgentOverlaySystemFiles, "<lowercase-kebab-slug>.md"]
9710
+ supportedFiles: isThreadWorkspace ? ["<lowercase-kebab-slug>.md", "<lowercase-kebab-slug>.txt", "<lowercase-kebab-slug>.csv"] : [...supportedAgentOverlaySystemFiles, "<lowercase-kebab-slug>.md"]
9847
9711
  }
9848
9712
  });
9849
9713
  }
@@ -11326,7 +11190,7 @@ function positiveInt2(raw, fallback) {
11326
11190
  function requestTimeoutMs(totalTimeoutMs) {
11327
11191
  return Math.max(1e3, Math.min(totalTimeoutMs, 1e4));
11328
11192
  }
11329
- function asRecord5(value) {
11193
+ function asRecord4(value) {
11330
11194
  return value && typeof value === "object" && !Array.isArray(value) ? value : null;
11331
11195
  }
11332
11196
  function asString(value) {
@@ -11376,9 +11240,9 @@ function cliTokenFromPoll(payload) {
11376
11240
  return asString(payload.cliToken) ?? asString(payload.cli_token) ?? asString(payload.token);
11377
11241
  }
11378
11242
  function unwrapMutationResult(value) {
11379
- const record = asRecord5(value);
11243
+ const record = asRecord4(value);
11380
11244
  if (!record) return null;
11381
- const data = asRecord5(record.data);
11245
+ const data = asRecord4(record.data);
11382
11246
  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"))) {
11383
11247
  return data;
11384
11248
  }
@@ -11443,7 +11307,7 @@ async function runTokenLogin(cmd, opts) {
11443
11307
  exitCode: mapStatusToExitCode(status.error.status)
11444
11308
  });
11445
11309
  }
11446
- const statusData = asRecord5(status.result.data.cliAuthStatus) ?? {};
11310
+ const statusData = asRecord4(status.result.data.cliAuthStatus) ?? {};
11447
11311
  const storage = await writeStoredToken(token, baseUrl);
11448
11312
  const configPath2 = opts.saveBaseUrl ? await persistBaseUrl(baseUrl) : void 0;
11449
11313
  return printEnvelopeAndExit({
@@ -11660,7 +11524,7 @@ async function runLogout(cmd) {
11660
11524
  });
11661
11525
  if (result.ok) {
11662
11526
  requestId = result.result.requestId;
11663
- const payload = asRecord5(result.result.data.revokeCliToken) ?? {};
11527
+ const payload = asRecord4(result.result.data.revokeCliToken) ?? {};
11664
11528
  revokedRemote = payload.ok !== false;
11665
11529
  } else {
11666
11530
  requestId = result.requestId;
@@ -11723,7 +11587,7 @@ async function runAuthStatus(cmd) {
11723
11587
  exitCode: mapStatusToExitCode(result.error.status)
11724
11588
  });
11725
11589
  }
11726
- const status = asRecord5(result.result.data.cliAuthStatus) ?? {};
11590
+ const status = asRecord4(result.result.data.cliAuthStatus) ?? {};
11727
11591
  const baseAuthStatus = status.baseAuthStatus;
11728
11592
  return printEnvelopeAndExit({
11729
11593
  envelope: envelope({
@@ -11990,6 +11854,26 @@ var RECENT_TOOL_SUPPORT_REGISTRY = [
11990
11854
  ]
11991
11855
  }
11992
11856
  }),
11857
+ entry({
11858
+ cliKey: "sketches",
11859
+ displayName: "Sketches",
11860
+ backend: backendToolKey("sketches"),
11861
+ routes: ["/sketches", "/sketches/[sketchId]"],
11862
+ capabilityCategories: ["collaboration", "design", "metadata", "read_only_discovery"],
11863
+ sensitiveOutputNotes: [
11864
+ "Sketch commands must not print document bytes, collaboration updates, embedded files, comments, or auth material."
11865
+ ],
11866
+ implementation: {
11867
+ milestone: "WAVE-12",
11868
+ status: "implemented_command_surface",
11869
+ enabledCommands: ["open", "list", "show", "create", "update-metadata"],
11870
+ forbiddenCommands: ["save-document", "render", "export", "import"],
11871
+ notes: [
11872
+ "The Sketch surface is limited to metadata and does not provide an editor, renderer, binary transport, or provider connector.",
11873
+ "Create and metadata update use the existing typed GraphQL mutations."
11874
+ ]
11875
+ }
11876
+ }),
11993
11877
  entry({
11994
11878
  cliKey: "time-tracking",
11995
11879
  displayName: "Time Tracking",
@@ -13027,6 +12911,158 @@ function registerWhiteboardsCommands(program) {
13027
12911
  });
13028
12912
  }
13029
12913
 
12914
+ // src/commands/sketches.ts
12915
+ var SKETCH_METADATA_SELECTION = "id name slug status priority archivedAt organizationId memberId teamIds documentGeneration documentVersion partytimeRoomId partytimeRoomVersion createdAt updatedAt";
12916
+ var SKETCHES_SELECTION = `{ count currentPage totalPages data { ${SKETCH_METADATA_SELECTION} } }`;
12917
+ var SKETCH_SELECTION = `{ ${SKETCH_METADATA_SELECTION} }`;
12918
+ function baseVariables4(contextOrganizationId) {
12919
+ return { organization_id: resolveOrganizationId(contextOrganizationId) };
12920
+ }
12921
+ function listFilters3(opts) {
12922
+ return {
12923
+ page: opts.page,
12924
+ per: opts.per,
12925
+ team_id: opts.teamId,
12926
+ member_id: opts.memberId,
12927
+ include_archived: opts.includeArchived
12928
+ };
12929
+ }
12930
+ function listVariableTypes3() {
12931
+ return {
12932
+ organization_id: "ID!",
12933
+ page: "Int",
12934
+ per: "Int",
12935
+ team_id: "ID",
12936
+ member_id: "ID",
12937
+ include_archived: "Boolean"
12938
+ };
12939
+ }
12940
+ async function runSketchQuery(cmd, config) {
12941
+ const context = await resolveCommandContext(cmd.optsWithGlobals());
12942
+ await runGraphqlQueryCommand({
12943
+ command: config.command,
12944
+ operationName: config.operationName,
12945
+ runtimeOptions: context.runtimeOptions,
12946
+ field: config.field,
12947
+ variables: normalizeGraphqlVariables2({
12948
+ ...baseVariables4(context.organizationId),
12949
+ ...config.variables
12950
+ }),
12951
+ ...config.variableTypes ? { variableTypes: config.variableTypes } : {},
12952
+ ...config.isList ? { isList: true } : {},
12953
+ ...config.isShow ? { isShow: true } : {},
12954
+ selectionSet: config.selectionSet
12955
+ });
12956
+ }
12957
+ function addListFilterOptions3(command) {
12958
+ return command.option("--page <page>").option("--per <per>").option("--team-id <teamId>").option("--member-id <memberId>").option("--include-archived <includeArchived>");
12959
+ }
12960
+ function sketchOpenData() {
12961
+ const tool = getRecentToolSupport("sketches");
12962
+ return {
12963
+ cliKey: "sketches",
12964
+ displayName: "Sketches",
12965
+ backend: {
12966
+ toolKey: tool?.backend.toolKey ?? "sketches",
12967
+ status: tool?.backend.status ?? "verified_wave_02",
12968
+ sourceMilestone: tool?.backend.sourceMilestone ?? "WAVE-02"
12969
+ },
12970
+ route: tool?.safeRouteTargets.primaryRoute ?? "/sketches",
12971
+ safeRouteTargets: tool?.safeRouteTargets ?? {
12972
+ primaryRoute: "/sketches",
12973
+ deepLinkTemplates: ["/sketches", "/sketches/[sketchId]"],
12974
+ status: "verified_wave_03",
12975
+ sourceMilestone: "WAVE-03"
12976
+ },
12977
+ implementation: {
12978
+ enabledCommands: ["open", "list", "show", "create", "update-metadata"],
12979
+ excludedCommands: ["save-document", "render", "export", "import"]
12980
+ },
12981
+ sensitiveOutputNotes: tool?.sensitiveOutputNotes ?? [
12982
+ "Sketch commands return metadata only and never return document bytes, collaboration updates, embedded files, comments, or tokens."
12983
+ ]
12984
+ };
12985
+ }
12986
+ function registerSketchCommands(program) {
12987
+ const sketches = program.command("sketches").description("Sketch metadata operations with bounded create and update support");
12988
+ sketches.command("open").description("Return verified Sketches app routes without opening a browser").option("--readable", "Print the primary route path only").option("--json", "Emit the stable JSON envelope").action((opts) => {
12989
+ const data = sketchOpenData();
12990
+ if (opts.readable && !opts.json) return printTextAndExit({ text: String(data.route) });
12991
+ return printEnvelopeAndExit({
12992
+ envelope: {
12993
+ ok: true,
12994
+ command: "sketches.open",
12995
+ status: 200,
12996
+ data,
12997
+ error: null,
12998
+ meta: { requestId: "local_sketches" }
12999
+ }
13000
+ });
13001
+ });
13002
+ addListFilterOptions3(sketches.command("list").description("Read safe Sketch metadata")).action(
13003
+ async (opts, cmd) => {
13004
+ await runSketchQuery(cmd, {
13005
+ command: "sketches.list",
13006
+ operationName: "Sketches",
13007
+ field: "sketches",
13008
+ variables: listFilters3(opts),
13009
+ variableTypes: listVariableTypes3(),
13010
+ isList: true,
13011
+ selectionSet: SKETCHES_SELECTION
13012
+ });
13013
+ }
13014
+ );
13015
+ sketches.command("show").description("Read safe Sketch detail metadata").requiredOption("--slug <slug>").action(async (opts, cmd) => {
13016
+ await runSketchQuery(cmd, {
13017
+ command: "sketches.show",
13018
+ operationName: "Sketch",
13019
+ field: "sketch",
13020
+ variables: { slug: opts.slug },
13021
+ variableTypes: { organization_id: "ID!", slug: "ID!" },
13022
+ isShow: true,
13023
+ selectionSet: SKETCH_SELECTION
13024
+ });
13025
+ });
13026
+ sketches.command("create").description("Create a Sketch with a required team and idempotency key").requiredOption("--data-json <dataJson>", 'Sketch JSON or {"sketch": {...}}').action(async (opts, cmd) => {
13027
+ const context = await resolveCommandContext(cmd.optsWithGlobals());
13028
+ const body = __testables.normalizeBody(String(opts.dataJson), "sketch");
13029
+ assertOperationPayload("sketches.create", body);
13030
+ await runGraphqlMutationCommand({
13031
+ command: "sketches.create",
13032
+ runtimeOptions: context.runtimeOptions,
13033
+ field: "create_sketch",
13034
+ variables: {
13035
+ organization_id: resolveOrganizationId(context.organizationId),
13036
+ params: body
13037
+ },
13038
+ variableTypes: {
13039
+ organization_id: "ID!",
13040
+ params: "CreateSketchParamsInput!"
13041
+ }
13042
+ });
13043
+ });
13044
+ sketches.command("update-metadata").description("Update bounded Sketch metadata; document content is never accepted").requiredOption("--id <id>").requiredOption("--data-json <dataJson>", 'Sketch metadata JSON or {"sketch": {...}}').action(async (opts, cmd) => {
13045
+ const context = await resolveCommandContext(cmd.optsWithGlobals());
13046
+ const body = __testables.normalizeBody(String(opts.dataJson), "sketch");
13047
+ assertOperationPayload("sketches.update-metadata", body);
13048
+ await runGraphqlMutationCommand({
13049
+ command: "sketches.update-metadata",
13050
+ runtimeOptions: context.runtimeOptions,
13051
+ field: "update_sketch",
13052
+ variables: {
13053
+ organization_id: resolveOrganizationId(context.organizationId),
13054
+ sketch_id: String(opts.id),
13055
+ params: body
13056
+ },
13057
+ variableTypes: {
13058
+ organization_id: "ID!",
13059
+ sketch_id: "ID!",
13060
+ params: "UpdateSketchParamsInput!"
13061
+ }
13062
+ });
13063
+ });
13064
+ }
13065
+
13030
13066
  // src/commands/timeTracking.ts
13031
13067
  var TIME_TRACKING_ENTRY_SELECTION = "id organizationId memberId memberName taskId projectId projectName labelId createdByMemberId localDate durationMinutes startMinute endMinute startedAt endedAt status source createdAt updatedAt";
13032
13068
  var TIME_TRACKING_ENTRIES_SELECTION = `{ count currentPage totalPages data { ${TIME_TRACKING_ENTRY_SELECTION} } }`;
@@ -13057,7 +13093,7 @@ var TIME_TRACKING_FORBIDDEN_COMMANDS = [
13057
13093
  "payroll",
13058
13094
  "billing"
13059
13095
  ];
13060
- function baseVariables4(contextOrganizationId) {
13096
+ function baseVariables5(contextOrganizationId) {
13061
13097
  return {
13062
13098
  organization_id: resolveOrganizationId(contextOrganizationId)
13063
13099
  };
@@ -13112,7 +13148,7 @@ async function runTimeTrackingQuery(cmd, config) {
13112
13148
  runtimeOptions: context.runtimeOptions,
13113
13149
  field: config.field,
13114
13150
  variables: normalizeGraphqlVariables2({
13115
- ...baseVariables4(context.organizationId),
13151
+ ...baseVariables5(context.organizationId),
13116
13152
  ...config.variables
13117
13153
  }),
13118
13154
  variableTypes: config.variableTypes,
@@ -13374,11 +13410,11 @@ function sanitizePlannerJson(value) {
13374
13410
  }
13375
13411
  return output;
13376
13412
  }
13377
- function asRecord6(value) {
13413
+ function asRecord5(value) {
13378
13414
  return value && typeof value === "object" && !Array.isArray(value) ? value : null;
13379
13415
  }
13380
13416
  function readPlannerStateKey(value, keys) {
13381
- const record = asRecord6(value);
13417
+ const record = asRecord5(value);
13382
13418
  if (!record) {
13383
13419
  return null;
13384
13420
  }
@@ -13573,6 +13609,7 @@ var MAIL_ENABLED_COMMANDS = [
13573
13609
  "open",
13574
13610
  "validate-provider",
13575
13611
  "workspace",
13612
+ "relay-evidence",
13576
13613
  "accounts",
13577
13614
  "messages",
13578
13615
  "conversations",
@@ -13638,6 +13675,9 @@ var MAIL_SETTINGS_SELECTION = "{ id organizationId memberId defaultMailAccountId
13638
13675
  var MAIL_UNREAD_COUNT_SELECTION = "{ total byAccount byLabel }";
13639
13676
  var MAIL_SYNC_STATUS_SELECTION = "{ id status operationStatus operationToolKey accountId accountIds page per view importedCount updatedCount providerCount counts errorCode statusCode queuedAt startedAt completedAt createdAt updatedAt }";
13640
13677
  var MAIL_WORKSPACE_SELECTION = `{ accounts ${MAIL_ACCOUNT_SELECTION} messages ${MAIL_MESSAGES_SELECTION} labels ${MAIL_LABEL_SELECTION} snippets ${MAIL_SNIPPET_SELECTION} settings ${MAIL_SETTINGS_SELECTION} unreadCount ${MAIL_UNREAD_COUNT_SELECTION} }`;
13678
+ var MAIL_RELAY_EVIDENCE_ACCOUNT_SELECTION = "{ id provider service status connectionState syncStatus emailAddress displayName lastSyncedAt }";
13679
+ var MAIL_RELAY_EVIDENCE_MESSAGE_SELECTION = "{ id mailAccountId subject from status direction sentAt receivedAt snippet createdAt updatedAt }";
13680
+ var MAIL_RELAY_EVIDENCE_SELECTION = `{ accounts ${MAIL_RELAY_EVIDENCE_ACCOUNT_SELECTION} messages { count currentPage totalPages data ${MAIL_RELAY_EVIDENCE_MESSAGE_SELECTION} } }`;
13641
13681
  var OUTLOOK_PROVIDER_VALIDATION_EVIDENCE = {
13642
13682
  provider: "microsoft",
13643
13683
  oauthProviderId: "wave-microsoft-outlook",
@@ -13802,7 +13842,8 @@ function buildMailOpenData() {
13802
13842
  forbiddenCommands: [...MAIL_FORBIDDEN_COMMANDS]
13803
13843
  },
13804
13844
  sensitiveOutputNotes: tool?.sensitiveOutputNotes ?? [
13805
- "Mail commands are metadata-only and must not print message bodies, subjects, snippets, contacts, attachments, provider payloads, token material, account addresses/display names, label names/colors, snippet content, preferences, signatures, sync search text, sync error bodies, or user-authored mail content."
13845
+ "Default Mail commands are metadata-only and must not print message bodies, subjects, snippets, contacts, attachments, provider payloads, token material, account addresses/display names, label names/colors, snippet content, preferences, signatures, sync search text, sync error bodies, or user-authored mail content.",
13846
+ "mail relay-evidence is the explicit bounded exception for an authenticated, user-authorized relay: it exposes mailbox identity plus sender, subject, date, and snippet metadata, but never bodies, recipients, attachments, provider IDs, or token material."
13806
13847
  ]
13807
13848
  };
13808
13849
  }
@@ -13915,6 +13956,26 @@ function registerMailCommands(program) {
13915
13956
  isShow: true
13916
13957
  });
13917
13958
  });
13959
+ addPaginationOptions(
13960
+ mail.command("relay-evidence").description(
13961
+ "Read bounded mailbox identity and recent message metadata for an explicitly authorized relay"
13962
+ ).option("--account-id <accountId>")
13963
+ ).action(async (opts, cmd) => {
13964
+ await runMailQuery(cmd, opts, {
13965
+ command: "mail.relay-evidence",
13966
+ operationName: "MailRelayEvidence",
13967
+ field: "mail_workspace",
13968
+ variables: mailWorkspaceVariables,
13969
+ variableTypes: {
13970
+ organization_id: "ID!",
13971
+ account_id: "ID",
13972
+ page: "Int",
13973
+ per: "Int"
13974
+ },
13975
+ selectionSet: MAIL_RELAY_EVIDENCE_SELECTION,
13976
+ isShow: true
13977
+ });
13978
+ });
13918
13979
  mail.command("accounts").description("Read safe Mail account metadata").action(async (opts, cmd) => {
13919
13980
  await runMailQuery(cmd, opts, {
13920
13981
  command: "mail.accounts",
@@ -15956,7 +16017,7 @@ var URL_OR_TRANSPORT_KEY = /(?:^|_)(?:url|uri|token|nonce|post_fields|postfields
15956
16017
  function isRecord7(value) {
15957
16018
  return Boolean(value) && typeof value === "object" && !Array.isArray(value);
15958
16019
  }
15959
- function asNonEmptyString6(value) {
16020
+ function asNonEmptyString5(value) {
15960
16021
  if (typeof value !== "string") return null;
15961
16022
  const trimmed = value.trim();
15962
16023
  return trimmed.length > 0 ? trimmed : null;
@@ -16001,7 +16062,7 @@ function parseCreatePayload(raw, mode) {
16001
16062
  ["name", "subject", "message", "expires_at", "visibility", "metadata", "recipients"],
16002
16063
  "--data-json"
16003
16064
  );
16004
- const parsedMode = asNonEmptyString6(mode);
16065
+ const parsedMode = asNonEmptyString5(mode);
16005
16066
  if (parsedMode !== "request" && parsedMode !== "self_sign") {
16006
16067
  throw new CliError({
16007
16068
  message: "signatures create requires --mode request or --mode self_sign.",
@@ -16019,9 +16080,9 @@ function parseUpdatePayload(raw, options) {
16019
16080
  ["name", "subject", "message", "expires_at", "visibility", "recipients", "fields"],
16020
16081
  "--data-json"
16021
16082
  );
16022
- const name = asNonEmptyString6(options.name);
16023
- const subject = asNonEmptyString6(options.subject);
16024
- const message = asNonEmptyString6(options.message);
16083
+ const name = asNonEmptyString5(options.name);
16084
+ const subject = asNonEmptyString5(options.subject);
16085
+ const message = asNonEmptyString5(options.message);
16025
16086
  const patch = {
16026
16087
  ...data,
16027
16088
  ...name ? { name } : {},
@@ -16156,8 +16217,8 @@ function requireUploadTarget(payload) {
16156
16217
  exitCode: EXIT_CODES.networkOrUpstream
16157
16218
  });
16158
16219
  }
16159
- const postUrl = asNonEmptyString6(attributes.postUrl);
16160
- const fileKey = asNonEmptyString6(attributes.getUrl);
16220
+ const postUrl = asNonEmptyString5(attributes.postUrl);
16221
+ const fileKey = asNonEmptyString5(attributes.getUrl);
16161
16222
  const rawPostFields = attributes.postFields;
16162
16223
  if (!postUrl || !fileKey || !isRecord7(rawPostFields) || !fileKey.startsWith("uploads/signatures/")) {
16163
16224
  throw new CliError({
@@ -16628,7 +16689,7 @@ var AUTOMATION_RUN_STATUS_SELECTION = `{
16628
16689
  queuedAt
16629
16690
  completedAt
16630
16691
  }`;
16631
- function asRecord7(value) {
16692
+ function asRecord6(value) {
16632
16693
  return value && typeof value === "object" && !Array.isArray(value) ? value : null;
16633
16694
  }
16634
16695
  function asRequiredString(value) {
@@ -16659,7 +16720,7 @@ function requirePaginationInteger(value, key, minimum) {
16659
16720
  });
16660
16721
  }
16661
16722
  function normalizeAutomationList(payload) {
16662
- const page = asRecord7(payload);
16723
+ const page = asRecord6(payload);
16663
16724
  if (!page || !Array.isArray(page.data)) {
16664
16725
  throw new CliError({
16665
16726
  message: "Automation list response did not include a paginated data collection.",
@@ -16670,8 +16731,8 @@ function normalizeAutomationList(payload) {
16670
16731
  }
16671
16732
  const rows = page.data;
16672
16733
  const data = rows.map((value) => {
16673
- const row = asRecord7(value);
16674
- const attributes = asRecord7(row?.attributes);
16734
+ const row = asRecord6(value);
16735
+ const attributes = asRecord6(row?.attributes);
16675
16736
  if (!row || !attributes) {
16676
16737
  throw new CliError({
16677
16738
  message: "Automation list response included a malformed automation record.",
@@ -16756,13 +16817,13 @@ function parseJsonOption(value, optionName, schema) {
16756
16817
  return schema.parse(parseJson(String(value), optionName));
16757
16818
  }
16758
16819
  function normalizePersistedCreatePayload(payload) {
16759
- const mutation = asRecord7(payload);
16760
- const mutationData = asRecord7(mutation?.data);
16761
- const persisted = asRecord7(mutationData?.data) ?? mutationData;
16762
- const attributes = asRecord7(persisted?.attributes);
16763
- const automationExecution = asRecord7(attributes?.automation_execution) ?? asRecord7(attributes?.automationExecution);
16764
- const meta = asRecord7(mutationData?.meta);
16765
- const idempotency = asRecord7(meta?.atlas_idempotency);
16820
+ const mutation = asRecord6(payload);
16821
+ const mutationData = asRecord6(mutation?.data);
16822
+ const persisted = asRecord6(mutationData?.data) ?? mutationData;
16823
+ const attributes = asRecord6(persisted?.attributes);
16824
+ const automationExecution = asRecord6(attributes?.automation_execution) ?? asRecord6(attributes?.automationExecution);
16825
+ const meta = asRecord6(mutationData?.meta);
16826
+ const idempotency = asRecord6(meta?.atlas_idempotency);
16766
16827
  const id = asRequiredString(persisted?.id);
16767
16828
  const slug = asRequiredString(persisted?.slug) ?? asRequiredString(attributes?.slug);
16768
16829
  const replay = idempotency?.replay;
@@ -16793,10 +16854,10 @@ function normalizePersistedCreatePayload(payload) {
16793
16854
  };
16794
16855
  }
16795
16856
  function normalizePersistedUpdatePayload(payload) {
16796
- const mutation = asRecord7(payload);
16797
- const mutationData = asRecord7(mutation?.data);
16798
- const persisted = asRecord7(mutationData?.data) ?? mutationData;
16799
- const attributes = asRecord7(persisted?.attributes);
16857
+ const mutation = asRecord6(payload);
16858
+ const mutationData = asRecord6(mutation?.data);
16859
+ const persisted = asRecord6(mutationData?.data) ?? mutationData;
16860
+ const attributes = asRecord6(persisted?.attributes);
16800
16861
  const id = asRequiredString(persisted?.id);
16801
16862
  const slug = asRequiredString(persisted?.slug) ?? asRequiredString(attributes?.slug);
16802
16863
  const updateVersion = asRequiredString(persisted?.updateVersion) ?? asRequiredString(attributes?.updateVersion) ?? asRequiredString(attributes?.update_version);
@@ -16817,7 +16878,7 @@ function normalizePersistedUpdatePayload(payload) {
16817
16878
  };
16818
16879
  }
16819
16880
  function normalizeAutomationRunPayload(payload) {
16820
- const mutation = asRecord7(payload);
16881
+ const mutation = asRecord6(payload);
16821
16882
  if (!mutation) {
16822
16883
  throw new CliError({
16823
16884
  message: "Automation run response did not include a mutation payload.",
@@ -16835,7 +16896,7 @@ function normalizeAutomationRunPayload(payload) {
16835
16896
  data: mutation.data ?? null
16836
16897
  };
16837
16898
  }
16838
- const data = asRecord7(mutation.data);
16899
+ const data = asRecord6(mutation.data);
16839
16900
  const automationTaskId = asRequiredString(data?.automation_task_id);
16840
16901
  const automationTaskSlug = asRequiredString(data?.automation_task_slug);
16841
16902
  const agentId = asRequiredString(data?.agent_id);
@@ -17574,8 +17635,8 @@ name
17574
17635
  categories
17575
17636
  availability
17576
17637
  integrationKey
17577
- arcadeProvider
17578
- arcadeService
17638
+ connectorProvider
17639
+ connectorService
17579
17640
  logoAssetPath
17580
17641
  `.trim();
17581
17642
  var OVERVIEW_SELECTION = `
@@ -17909,6 +17970,7 @@ var PRIMARY_NAMESPACES = [
17909
17970
  "support",
17910
17971
  "recognition",
17911
17972
  "whiteboards",
17973
+ "sketches",
17912
17974
  "time-tracking",
17913
17975
  "planner",
17914
17976
  "mail",
@@ -17940,9 +18002,7 @@ var ADVANCED_NAMESPACES = [
17940
18002
  "stand-ups",
17941
18003
  "news",
17942
18004
  "questions",
17943
- "pulse",
17944
18005
  "surveys",
17945
- "feedbacks",
17946
18006
  "accountability",
17947
18007
  "kpis",
17948
18008
  "scorecard-groups",
@@ -18256,6 +18316,28 @@ var NAMESPACE_DOCS = {
18256
18316
  commands: ["open", "list", "show"]
18257
18317
  }
18258
18318
  },
18319
+ sketches: {
18320
+ name: "sketches",
18321
+ tier: "primary",
18322
+ description: "Sketch metadata, bounded create/update operations, and verified app-route metadata.",
18323
+ examples: [
18324
+ "wave sketches list --page 1 --per 20",
18325
+ "wave sketches show --slug SKT-02",
18326
+ `wave sketches create --data-json '{"name":"Design review","teams_ids":["team-1"],"creation_key":"design-review-1"}'`,
18327
+ `wave sketches update-metadata --id 123 --data-json '{"name":"Design review"}'`,
18328
+ "wave sketches open"
18329
+ ],
18330
+ schema: {
18331
+ output: "json-envelope-default",
18332
+ mutates: true,
18333
+ safety: [
18334
+ "Uses verified GraphQL fields sketches, sketch, createSketch, and updateSketch.",
18335
+ "Create requires a team and an idempotency creation key; update accepts only bounded metadata fields.",
18336
+ "Never accepts or emits native document bytes, collaboration updates, render/export data, embedded files, comments, or tokens."
18337
+ ],
18338
+ commands: ["open", "list", "show", "create", "update-metadata"]
18339
+ }
18340
+ },
18259
18341
  "time-tracking": {
18260
18342
  name: "time-tracking",
18261
18343
  tier: "primary",
@@ -18316,9 +18398,10 @@ var NAMESPACE_DOCS = {
18316
18398
  mail: {
18317
18399
  name: "mail",
18318
18400
  tier: "primary",
18319
- description: "Mail read-only metadata for workspace, accounts, messages, conversations, labels, snippets, settings, sync status, and verified app route metadata.",
18401
+ description: "Mail read-only metadata for workspace, explicitly authorized relay evidence, accounts, messages, conversations, labels, snippets, settings, sync status, and verified app route metadata.",
18320
18402
  examples: [
18321
18403
  "wave mail workspace --page 1 --per 20",
18404
+ "wave mail relay-evidence --account-id 123 --page 1 --per 20",
18322
18405
  "wave mail accounts",
18323
18406
  "wave mail messages --account-id 123 --view inbox --page 1 --per 20",
18324
18407
  "wave mail conversations --account-id 123 --view inbox --page 1 --per 20",
@@ -18340,7 +18423,8 @@ var NAMESPACE_DOCS = {
18340
18423
  "Microsoft Outlook Mail maps to service outlook_mail and Outlook Calendar maps to service outlook_calendar with custom OAuth provider wave-microsoft-outlook.",
18341
18424
  "Uses the verified WAVE-03 safe app route /mail.",
18342
18425
  "Account output is limited to ids, provider/service, status, connection state, sync status, and timestamps.",
18343
- "Message and conversation output omits bodies, subjects, snippets, contacts, attachments, provider payloads, provider ids, raw thread ids, and user-authored mail content.",
18426
+ "Default message and conversation output omits bodies, subjects, snippets, contacts, attachments, provider payloads, provider ids, raw thread ids, and user-authored mail content.",
18427
+ "relay-evidence is an explicit authenticated relay surface limited to mailbox identity plus sender, subject, date, and snippet metadata; it still omits bodies, recipients, attachments, provider ids, and token material.",
18344
18428
  "Label, snippet, settings, and sync-status output omits user label names/colors, snippet title/shortcut/body, signatures, preferences, sync search text, operation reasons, error bodies, and token material.",
18345
18429
  "Does not expose send, reply, reply-all, forward, draft, provider-action, sync/connect/disconnect, mark, archive, trash, star, label/snippet CRUD, export, print, or write commands."
18346
18430
  ],
@@ -18348,6 +18432,7 @@ var NAMESPACE_DOCS = {
18348
18432
  "open",
18349
18433
  "validate-provider",
18350
18434
  "workspace",
18435
+ "relay-evidence",
18351
18436
  "accounts",
18352
18437
  "messages",
18353
18438
  "conversations",
@@ -18944,7 +19029,11 @@ function buildCli(options) {
18944
19029
  "Explicit organization ID override"
18945
19030
  ).option(
18946
19031
  "--config <configPath>",
18947
- "Optional JSON config file (default: WAVE_CONFIG_PATH or ~/.wave/config.json when present)"
19032
+ "Optional JSON config file (default: ~/.wave/config.json when present)"
19033
+ ).addOption(
19034
+ new import_commander2.Option("--auth-home <path>", "Credential storage directory (default: ~/.wave)")
19035
+ ).addOption(
19036
+ new import_commander2.Option("--auth-storage <mode>", "Credential storage mode").choices(["auto", "keychain", "file", "disabled"]).default("auto")
18948
19037
  ).option("--timeout-ms <timeoutMs>", "HTTP timeout in milliseconds").option("--agent-name <agentName>", "Agent name for tracing").option("--agent-run-id <agentRunId>", "Agent run identifier for tracing").option("--request-id <requestId>", "Request identifier").option(
18949
19038
  "--atlas-member-id <memberId>",
18950
19039
  "Atlas ledger member ID (prefer WAVE_ATLAS_MEMBER_ID env var)"
@@ -18976,6 +19065,14 @@ function buildCli(options) {
18976
19065
  "--openapi-version <openapiVersion>",
18977
19066
  "Optional pinned OpenAPI version/hash"
18978
19067
  ).exitOverride();
19068
+ program.hook("preAction", (_thisCommand, actionCommand) => {
19069
+ const runtimeOptions = actionCommand.optsWithGlobals();
19070
+ configureAuthStorage({
19071
+ ...runtimeOptions.authHome ? { home: runtimeOptions.authHome } : {},
19072
+ ...runtimeOptions.config ? { configPath: runtimeOptions.config } : {},
19073
+ ...runtimeOptions.authStorage ? { mode: runtimeOptions.authStorage } : {}
19074
+ });
19075
+ });
18979
19076
  setInternalCliOptions(program, options?.internal);
18980
19077
  registerTaskCommands(program);
18981
19078
  registerProjectCommands(program);
@@ -19000,6 +19097,7 @@ function buildCli(options) {
19000
19097
  registerSupportCommands(program);
19001
19098
  registerRecognitionCommands(program);
19002
19099
  registerWhiteboardsCommands(program);
19100
+ registerSketchCommands(program);
19003
19101
  registerTimeTrackingCommands(program);
19004
19102
  registerPlannerCommands(program);
19005
19103
  registerMailCommands(program);
@@ -19264,9 +19362,10 @@ function withTrustedMachineAuth(auth, callback) {
19264
19362
  for (const key of Object.keys(process.env)) {
19265
19363
  if (key.startsWith("WAVE_")) delete process.env[key];
19266
19364
  }
19267
- process.env.WAVE_CLI_AUTH_STORAGE = "disabled";
19268
- process.env.WAVE_CLI_HOME = "/dev/null";
19269
- return withMachineRuntimeAuth(auth, callback).finally(() => {
19365
+ return withAuthStorageOptions(
19366
+ { home: "/dev/null", mode: "disabled" },
19367
+ () => withMachineRuntimeAuth(auth, callback)
19368
+ ).finally(() => {
19270
19369
  for (const key of Object.keys(process.env)) {
19271
19370
  if (key.startsWith("WAVE_")) delete process.env[key];
19272
19371
  }
@@ -19473,7 +19572,15 @@ async function maybeRunMachineExecute(argv, program) {
19473
19572
  }
19474
19573
  try {
19475
19574
  await withTrustedMachineAuth(auth, async () => {
19476
- await program.parseAsync([process.execPath, "wave", ...commandArgs(resolved.command, normalizedInput)]);
19575
+ await program.parseAsync([
19576
+ process.execPath,
19577
+ "wave",
19578
+ "--auth-storage",
19579
+ "disabled",
19580
+ "--auth-home",
19581
+ "/dev/null",
19582
+ ...commandArgs(resolved.command, normalizedInput)
19583
+ ]);
19477
19584
  });
19478
19585
  } catch (error) {
19479
19586
  if (isEnvelopeEmittedSignal(error)) return true;