@displaydev/cli 0.18.0 → 0.19.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -392,6 +392,141 @@ export var ApiClient = /*#__PURE__*/ function() {
392
392
  }).call(this);
393
393
  }
394
394
  },
395
+ {
396
+ key: "addComment",
397
+ value: // ── Comments (feat-comments §3) ──────────────────────────────────────
398
+ // 1:1 with the public REST endpoints under
399
+ // `/v1/artifacts/:shortId/comments` and `/v1/comments/:commentId/...`.
400
+ // KB-page subjects 404 until KB ships.
401
+ function addComment(shortId, params) {
402
+ return _async_to_generator(function() {
403
+ return _ts_generator(this, function(_state) {
404
+ return [
405
+ 2,
406
+ this.request('POST', "/v1/artifacts/".concat(shortId, "/comments"), params)
407
+ ];
408
+ });
409
+ }).call(this);
410
+ }
411
+ },
412
+ {
413
+ key: "listComments",
414
+ value: function listComments(shortId, params) {
415
+ return _async_to_generator(function() {
416
+ var qs, suffix;
417
+ return _ts_generator(this, function(_state) {
418
+ qs = new URLSearchParams();
419
+ if (params === null || params === void 0 ? void 0 : params.status) {
420
+ qs.set('status', params.status);
421
+ }
422
+ if (params === null || params === void 0 ? void 0 : params.since) {
423
+ qs.set('since', params.since);
424
+ }
425
+ suffix = qs.toString() ? "?".concat(qs.toString()) : '';
426
+ return [
427
+ 2,
428
+ this.request('GET', "/v1/artifacts/".concat(shortId, "/comments").concat(suffix))
429
+ ];
430
+ });
431
+ }).call(this);
432
+ }
433
+ },
434
+ {
435
+ key: "editComment",
436
+ value: function editComment(commentId, body) {
437
+ return _async_to_generator(function() {
438
+ return _ts_generator(this, function(_state) {
439
+ return [
440
+ 2,
441
+ this.request('POST', "/v1/comments/".concat(commentId, "/edit"), {
442
+ body: body
443
+ })
444
+ ];
445
+ });
446
+ }).call(this);
447
+ }
448
+ },
449
+ {
450
+ key: "deleteComment",
451
+ value: function deleteComment(commentId) {
452
+ return _async_to_generator(function() {
453
+ return _ts_generator(this, function(_state) {
454
+ switch(_state.label){
455
+ case 0:
456
+ return [
457
+ 4,
458
+ this.request('DELETE', "/v1/comments/".concat(commentId))
459
+ ];
460
+ case 1:
461
+ _state.sent();
462
+ return [
463
+ 2
464
+ ];
465
+ }
466
+ });
467
+ }).call(this);
468
+ }
469
+ },
470
+ {
471
+ key: "resolveThread",
472
+ value: function resolveThread(commentId) {
473
+ return _async_to_generator(function() {
474
+ return _ts_generator(this, function(_state) {
475
+ return [
476
+ 2,
477
+ this.request('POST', "/v1/comments/".concat(commentId, "/resolve"))
478
+ ];
479
+ });
480
+ }).call(this);
481
+ }
482
+ },
483
+ {
484
+ key: "reopenThread",
485
+ value: function reopenThread(commentId) {
486
+ return _async_to_generator(function() {
487
+ return _ts_generator(this, function(_state) {
488
+ return [
489
+ 2,
490
+ this.request('POST', "/v1/comments/".concat(commentId, "/reopen"))
491
+ ];
492
+ });
493
+ }).call(this);
494
+ }
495
+ },
496
+ {
497
+ key: "watchArtifact",
498
+ value: function watchArtifact(shortId) {
499
+ return _async_to_generator(function() {
500
+ return _ts_generator(this, function(_state) {
501
+ return [
502
+ 2,
503
+ this.request('POST', "/v1/artifacts/".concat(shortId, "/watch"))
504
+ ];
505
+ });
506
+ }).call(this);
507
+ }
508
+ },
509
+ {
510
+ key: "unwatchArtifact",
511
+ value: function unwatchArtifact(shortId) {
512
+ return _async_to_generator(function() {
513
+ return _ts_generator(this, function(_state) {
514
+ switch(_state.label){
515
+ case 0:
516
+ return [
517
+ 4,
518
+ this.request('DELETE', "/v1/artifacts/".concat(shortId, "/watch"))
519
+ ];
520
+ case 1:
521
+ _state.sent();
522
+ return [
523
+ 2
524
+ ];
525
+ }
526
+ });
527
+ }).call(this);
528
+ }
529
+ },
395
530
  {
396
531
  key: "buildPublishForm",
397
532
  value: function buildPublishForm(params) {
@@ -972,6 +1107,15 @@ export var ApiClient = /*#__PURE__*/ function() {
972
1107
  }
973
1108
  throw new ApiError((_parsed_message = parsed.message) !== null && _parsed_message !== void 0 ? _parsed_message : "API error ".concat(res.status), res.status, parsed.details, parsed.reason, parsed.error);
974
1109
  case 3:
1110
+ // 204 No Content (and 205 Reset Content) carry no body. Calling
1111
+ // res.json() on them throws SyntaxError; return undefined so void-
1112
+ // typed callers (deleteComment, unwatchArtifact) are satisfied.
1113
+ if (res.status === 204 || res.status === 205) {
1114
+ return [
1115
+ 2,
1116
+ undefined
1117
+ ];
1118
+ }
975
1119
  return [
976
1120
  2,
977
1121
  res.json()
package/dist/main.js CHANGED
@@ -1703,6 +1703,537 @@ program.command('clear-logo').description('Remove the org logo (idempotent — s
1703
1703
  });
1704
1704
  })();
1705
1705
  });
1706
+ // --- comment add ---
1707
+ // `dsp comment add --artifact <shortId> --body "..." --anchor-json '<json>' [--parent <id>]`
1708
+ // Spec §3 maps to POST /v1/artifacts/:shortId/comments. Root posts
1709
+ // require a full anchor descriptor (textQuote prefix + exact + suffix
1710
+ // plus cssPath); replies inherit the root's anchor and must omit it.
1711
+ //
1712
+ // `--anchor-json` is intentionally the only anchor input. A bare-text
1713
+ // shortcut would have to fabricate prefix/suffix/cssPath, and the
1714
+ // underlying `dom-anchor-text-quote` resolver binds to the FIRST exact
1715
+ // match in the scope. Without prefix/suffix the resolver cannot
1716
+ // disambiguate duplicates and the comment can silently attach to the
1717
+ // wrong occurrence — see widget's anchor algorithm at
1718
+ // webapp/src/components/comments/anchor.ts:54. Forcing the caller to
1719
+ // supply the full descriptor (the agent has the source content; humans
1720
+ // can copy from the widget's selection JSON) keeps the bind reliable.
1721
+ program.command('comment').description('Comment-related subcommands. Run `dsp comment <cmd> --help` for each.').command('add').description('Post a root comment or reply on an artifact.').option('--artifact <shortId>', 'Artifact shortId (subject_type=artifact)').option('--kb-page <kbName...>', 'KB-page subject — pass two values: kb name then file path (subject_type=kb_page; not yet supported). Variadic (commander) — anything after `--kb-page` up to the next flag is consumed as the (kbName, filePath) tuple.').requiredOption('--body <text>', 'Comment body (≤10k chars)').option('--anchor-json <json>', 'Full anchor object as JSON: {"textQuote":{"prefix":"","exact":"...","suffix":""},"cssPath":"..."}. Required for root posts; omit for replies.').option('--parent <commentId>', 'Reply to this root comment id; omit for a root post').action(function(opts) {
1722
+ return _async_to_generator(function() {
1723
+ var subject, anchor, auth, client, result, err;
1724
+ return _ts_generator(this, function(_state) {
1725
+ switch(_state.label){
1726
+ case 0:
1727
+ subject = resolveSubjectFlags(opts);
1728
+ if (subject.kind === 'invalid') {
1729
+ console.error(subject.error);
1730
+ process.exit(1);
1731
+ }
1732
+ if (subject.kind === 'kb_page') {
1733
+ console.error('subject_type_not_implemented: KB-page subjects are not yet supported.');
1734
+ process.exit(1);
1735
+ }
1736
+ if (!opts.parent && !opts.anchorJson) {
1737
+ console.error('Root comments require --anchor-json. Use --parent <commentId> for a reply.');
1738
+ process.exit(1);
1739
+ }
1740
+ if (opts.parent && opts.anchorJson) {
1741
+ console.error('Replies inherit the root anchor — omit --anchor-json when --parent is set.');
1742
+ process.exit(1);
1743
+ }
1744
+ if (opts.anchorJson) {
1745
+ try {
1746
+ anchor = JSON.parse(opts.anchorJson);
1747
+ } catch (unused) {
1748
+ console.error('--anchor-json is not valid JSON.');
1749
+ process.exit(1);
1750
+ }
1751
+ }
1752
+ return [
1753
+ 4,
1754
+ resolveAuthOrConfig()
1755
+ ];
1756
+ case 1:
1757
+ auth = _state.sent();
1758
+ client = createClient(auth);
1759
+ _state.label = 2;
1760
+ case 2:
1761
+ _state.trys.push([
1762
+ 2,
1763
+ 4,
1764
+ ,
1765
+ 5
1766
+ ]);
1767
+ return [
1768
+ 4,
1769
+ client.addComment(subject.shortId, {
1770
+ body: opts.body,
1771
+ anchor: anchor,
1772
+ parentId: opts.parent
1773
+ })
1774
+ ];
1775
+ case 3:
1776
+ result = _state.sent();
1777
+ console.log(JSON.stringify(result, null, 2));
1778
+ return [
1779
+ 3,
1780
+ 5
1781
+ ];
1782
+ case 4:
1783
+ err = _state.sent();
1784
+ handleCommentApiError(err);
1785
+ return [
1786
+ 3,
1787
+ 5
1788
+ ];
1789
+ case 5:
1790
+ return [
1791
+ 2
1792
+ ];
1793
+ }
1794
+ });
1795
+ })();
1796
+ });
1797
+ // --- comment list ---
1798
+ program.commands.find(function(c) {
1799
+ return c.name() === 'comment';
1800
+ }).command('list').description('List comment threads on a subject.').option('--artifact <shortId>', 'Artifact shortId (subject_type=artifact)').option('--kb-page <kbName...>', 'KB-page subject — pass two values: kb name then file path (subject_type=kb_page; not yet supported). Variadic (commander) — anything after `--kb-page` up to the next flag is consumed as the (kbName, filePath) tuple.').option('--status <state>', 'open | resolved | all (default: open)').option('--since <iso>', 'ISO-8601 timestamp — filter to threads with activity at or after this point').action(function(opts) {
1801
+ return _async_to_generator(function() {
1802
+ var subject, auth, client, result, err;
1803
+ return _ts_generator(this, function(_state) {
1804
+ switch(_state.label){
1805
+ case 0:
1806
+ subject = resolveSubjectFlags(opts);
1807
+ if (subject.kind === 'invalid') {
1808
+ console.error(subject.error);
1809
+ process.exit(1);
1810
+ }
1811
+ if (subject.kind === 'kb_page') {
1812
+ console.error('subject_type_not_implemented: KB-page subjects are not yet supported.');
1813
+ process.exit(1);
1814
+ }
1815
+ if (opts.status && ![
1816
+ 'open',
1817
+ 'resolved',
1818
+ 'all'
1819
+ ].includes(opts.status)) {
1820
+ console.error("Invalid --status: ".concat(opts.status, ". Use open, resolved, or all."));
1821
+ process.exit(1);
1822
+ }
1823
+ return [
1824
+ 4,
1825
+ resolveAuthOrConfig()
1826
+ ];
1827
+ case 1:
1828
+ auth = _state.sent();
1829
+ client = createClient(auth);
1830
+ _state.label = 2;
1831
+ case 2:
1832
+ _state.trys.push([
1833
+ 2,
1834
+ 4,
1835
+ ,
1836
+ 5
1837
+ ]);
1838
+ return [
1839
+ 4,
1840
+ client.listComments(subject.shortId, {
1841
+ status: opts.status,
1842
+ since: opts.since
1843
+ })
1844
+ ];
1845
+ case 3:
1846
+ result = _state.sent();
1847
+ console.log(JSON.stringify(result, null, 2));
1848
+ return [
1849
+ 3,
1850
+ 5
1851
+ ];
1852
+ case 4:
1853
+ err = _state.sent();
1854
+ handleCommentApiError(err);
1855
+ return [
1856
+ 3,
1857
+ 5
1858
+ ];
1859
+ case 5:
1860
+ return [
1861
+ 2
1862
+ ];
1863
+ }
1864
+ });
1865
+ })();
1866
+ });
1867
+ // --- comment edit ---
1868
+ program.commands.find(function(c) {
1869
+ return c.name() === 'comment';
1870
+ }).command('edit <commentId>').description('Edit your own comment within the 5-minute author window.').requiredOption('--body <text>', 'New comment body').action(function(commentId, opts) {
1871
+ return _async_to_generator(function() {
1872
+ var auth, client, result, err;
1873
+ return _ts_generator(this, function(_state) {
1874
+ switch(_state.label){
1875
+ case 0:
1876
+ return [
1877
+ 4,
1878
+ resolveAuthOrConfig()
1879
+ ];
1880
+ case 1:
1881
+ auth = _state.sent();
1882
+ client = createClient(auth);
1883
+ _state.label = 2;
1884
+ case 2:
1885
+ _state.trys.push([
1886
+ 2,
1887
+ 4,
1888
+ ,
1889
+ 5
1890
+ ]);
1891
+ return [
1892
+ 4,
1893
+ client.editComment(commentId, opts.body)
1894
+ ];
1895
+ case 3:
1896
+ result = _state.sent();
1897
+ console.log(JSON.stringify(result, null, 2));
1898
+ return [
1899
+ 3,
1900
+ 5
1901
+ ];
1902
+ case 4:
1903
+ err = _state.sent();
1904
+ handleCommentApiError(err);
1905
+ return [
1906
+ 3,
1907
+ 5
1908
+ ];
1909
+ case 5:
1910
+ return [
1911
+ 2
1912
+ ];
1913
+ }
1914
+ });
1915
+ })();
1916
+ });
1917
+ // --- comment delete ---
1918
+ program.commands.find(function(c) {
1919
+ return c.name() === 'comment';
1920
+ }).command('delete <commentId>').description('Soft-delete a comment. Author / artifact creator / org admin.').action(function(commentId) {
1921
+ return _async_to_generator(function() {
1922
+ var auth, client, err;
1923
+ return _ts_generator(this, function(_state) {
1924
+ switch(_state.label){
1925
+ case 0:
1926
+ return [
1927
+ 4,
1928
+ resolveAuthOrConfig()
1929
+ ];
1930
+ case 1:
1931
+ auth = _state.sent();
1932
+ client = createClient(auth);
1933
+ _state.label = 2;
1934
+ case 2:
1935
+ _state.trys.push([
1936
+ 2,
1937
+ 4,
1938
+ ,
1939
+ 5
1940
+ ]);
1941
+ return [
1942
+ 4,
1943
+ client.deleteComment(commentId)
1944
+ ];
1945
+ case 3:
1946
+ _state.sent();
1947
+ console.log('Comment deleted.');
1948
+ return [
1949
+ 3,
1950
+ 5
1951
+ ];
1952
+ case 4:
1953
+ err = _state.sent();
1954
+ handleCommentApiError(err);
1955
+ return [
1956
+ 3,
1957
+ 5
1958
+ ];
1959
+ case 5:
1960
+ return [
1961
+ 2
1962
+ ];
1963
+ }
1964
+ });
1965
+ })();
1966
+ });
1967
+ // --- thread resolve / reopen ---
1968
+ var threadCmd = program.command('thread').description('Thread-level operations (resolve, reopen).');
1969
+ threadCmd.command('resolve <rootCommentId>').description('Mark a thread resolved. Thread participant / artifact creator / org admin.').action(function(commentId) {
1970
+ return _async_to_generator(function() {
1971
+ var auth, client, result, err;
1972
+ return _ts_generator(this, function(_state) {
1973
+ switch(_state.label){
1974
+ case 0:
1975
+ return [
1976
+ 4,
1977
+ resolveAuthOrConfig()
1978
+ ];
1979
+ case 1:
1980
+ auth = _state.sent();
1981
+ client = createClient(auth);
1982
+ _state.label = 2;
1983
+ case 2:
1984
+ _state.trys.push([
1985
+ 2,
1986
+ 4,
1987
+ ,
1988
+ 5
1989
+ ]);
1990
+ return [
1991
+ 4,
1992
+ client.resolveThread(commentId)
1993
+ ];
1994
+ case 3:
1995
+ result = _state.sent();
1996
+ console.log(JSON.stringify(result, null, 2));
1997
+ return [
1998
+ 3,
1999
+ 5
2000
+ ];
2001
+ case 4:
2002
+ err = _state.sent();
2003
+ handleCommentApiError(err);
2004
+ return [
2005
+ 3,
2006
+ 5
2007
+ ];
2008
+ case 5:
2009
+ return [
2010
+ 2
2011
+ ];
2012
+ }
2013
+ });
2014
+ })();
2015
+ });
2016
+ threadCmd.command('reopen <rootCommentId>').description('Reopen a resolved thread. Any authenticated user with view access.').action(function(commentId) {
2017
+ return _async_to_generator(function() {
2018
+ var auth, client, result, err;
2019
+ return _ts_generator(this, function(_state) {
2020
+ switch(_state.label){
2021
+ case 0:
2022
+ return [
2023
+ 4,
2024
+ resolveAuthOrConfig()
2025
+ ];
2026
+ case 1:
2027
+ auth = _state.sent();
2028
+ client = createClient(auth);
2029
+ _state.label = 2;
2030
+ case 2:
2031
+ _state.trys.push([
2032
+ 2,
2033
+ 4,
2034
+ ,
2035
+ 5
2036
+ ]);
2037
+ return [
2038
+ 4,
2039
+ client.reopenThread(commentId)
2040
+ ];
2041
+ case 3:
2042
+ result = _state.sent();
2043
+ console.log(JSON.stringify(result, null, 2));
2044
+ return [
2045
+ 3,
2046
+ 5
2047
+ ];
2048
+ case 4:
2049
+ err = _state.sent();
2050
+ handleCommentApiError(err);
2051
+ return [
2052
+ 3,
2053
+ 5
2054
+ ];
2055
+ case 5:
2056
+ return [
2057
+ 2
2058
+ ];
2059
+ }
2060
+ });
2061
+ })();
2062
+ });
2063
+ // --- watch / unwatch ---
2064
+ program.command('watch').description('Watch a subject for comment notifications.').option('--artifact <shortId>', 'Artifact shortId (subject_type=artifact)').option('--kb-page <kbName...>', 'KB-page subject — pass two values: kb name then file path (subject_type=kb_page; not yet supported). Variadic (commander) — anything after `--kb-page` up to the next flag is consumed as the (kbName, filePath) tuple.').action(function(opts) {
2065
+ return _async_to_generator(function() {
2066
+ var subject, auth, client, result, err;
2067
+ return _ts_generator(this, function(_state) {
2068
+ switch(_state.label){
2069
+ case 0:
2070
+ subject = resolveSubjectFlags(opts);
2071
+ if (subject.kind === 'invalid') {
2072
+ console.error(subject.error);
2073
+ process.exit(1);
2074
+ }
2075
+ if (subject.kind === 'kb_page') {
2076
+ console.error('subject_type_not_implemented: KB-page subjects are not yet supported.');
2077
+ process.exit(1);
2078
+ }
2079
+ return [
2080
+ 4,
2081
+ resolveAuthOrConfig()
2082
+ ];
2083
+ case 1:
2084
+ auth = _state.sent();
2085
+ client = createClient(auth);
2086
+ _state.label = 2;
2087
+ case 2:
2088
+ _state.trys.push([
2089
+ 2,
2090
+ 4,
2091
+ ,
2092
+ 5
2093
+ ]);
2094
+ return [
2095
+ 4,
2096
+ client.watchArtifact(subject.shortId)
2097
+ ];
2098
+ case 3:
2099
+ result = _state.sent();
2100
+ console.log(JSON.stringify(result, null, 2));
2101
+ return [
2102
+ 3,
2103
+ 5
2104
+ ];
2105
+ case 4:
2106
+ err = _state.sent();
2107
+ handleCommentApiError(err);
2108
+ return [
2109
+ 3,
2110
+ 5
2111
+ ];
2112
+ case 5:
2113
+ return [
2114
+ 2
2115
+ ];
2116
+ }
2117
+ });
2118
+ })();
2119
+ });
2120
+ program.command('unwatch').description('Unwatch a subject.').option('--artifact <shortId>', 'Artifact shortId (subject_type=artifact)').option('--kb-page <kbName...>', 'KB-page subject — pass two values: kb name then file path (subject_type=kb_page; not yet supported). Variadic (commander) — anything after `--kb-page` up to the next flag is consumed as the (kbName, filePath) tuple.').action(function(opts) {
2121
+ return _async_to_generator(function() {
2122
+ var subject, auth, client, err;
2123
+ return _ts_generator(this, function(_state) {
2124
+ switch(_state.label){
2125
+ case 0:
2126
+ subject = resolveSubjectFlags(opts);
2127
+ if (subject.kind === 'invalid') {
2128
+ console.error(subject.error);
2129
+ process.exit(1);
2130
+ }
2131
+ if (subject.kind === 'kb_page') {
2132
+ console.error('subject_type_not_implemented: KB-page subjects are not yet supported.');
2133
+ process.exit(1);
2134
+ }
2135
+ return [
2136
+ 4,
2137
+ resolveAuthOrConfig()
2138
+ ];
2139
+ case 1:
2140
+ auth = _state.sent();
2141
+ client = createClient(auth);
2142
+ _state.label = 2;
2143
+ case 2:
2144
+ _state.trys.push([
2145
+ 2,
2146
+ 4,
2147
+ ,
2148
+ 5
2149
+ ]);
2150
+ return [
2151
+ 4,
2152
+ client.unwatchArtifact(subject.shortId)
2153
+ ];
2154
+ case 3:
2155
+ _state.sent();
2156
+ console.log('Unwatched.');
2157
+ return [
2158
+ 3,
2159
+ 5
2160
+ ];
2161
+ case 4:
2162
+ err = _state.sent();
2163
+ handleCommentApiError(err);
2164
+ return [
2165
+ 3,
2166
+ 5
2167
+ ];
2168
+ case 5:
2169
+ return [
2170
+ 2
2171
+ ];
2172
+ }
2173
+ });
2174
+ })();
2175
+ });
2176
+ function resolveSubjectFlags(opts) {
2177
+ var hasArtifact = Boolean(opts.artifact);
2178
+ var kbPage = opts.kbPage;
2179
+ var hasKbPage = Array.isArray(kbPage) && kbPage.length > 0;
2180
+ if (hasArtifact && hasKbPage) {
2181
+ return {
2182
+ kind: 'invalid',
2183
+ error: 'Pass either --artifact or --kb-page, not both.'
2184
+ };
2185
+ }
2186
+ if (!hasArtifact && !hasKbPage) {
2187
+ return {
2188
+ kind: 'invalid',
2189
+ error: 'Pass --artifact <shortId> or --kb-page <kbName> <filePath>.'
2190
+ };
2191
+ }
2192
+ if (hasArtifact) {
2193
+ return {
2194
+ kind: 'artifact',
2195
+ shortId: opts.artifact
2196
+ };
2197
+ }
2198
+ if (kbPage.length !== 2) {
2199
+ return {
2200
+ kind: 'invalid',
2201
+ error: '--kb-page requires exactly two values: <kbName> <filePath>.'
2202
+ };
2203
+ }
2204
+ return {
2205
+ kind: 'kb_page',
2206
+ kbName: kbPage[0],
2207
+ filePath: kbPage[1],
2208
+ shortId: ''
2209
+ };
2210
+ }
2211
+ /**
2212
+ * Common error mapper for the comment / watch / thread subcommands.
2213
+ * Mirrors the ApiError handling on share/rename so 401 prompts a
2214
+ * re-login, 403 surfaces the API's reason verbatim, 404 shows a
2215
+ * concrete "not found", and 410 (signed-token failures from the
2216
+ * email-link routes) prints the API's message. Other errors fall
2217
+ * through to a generic stringify.
2218
+ */ function handleCommentApiError(err) {
2219
+ if (_instanceof(err, ApiError)) {
2220
+ if (err.status === 401) {
2221
+ console.error('Your credential is no longer valid. Run: dsp login (or rotate DISPLAYDEV_API_KEY).');
2222
+ process.exit(1);
2223
+ }
2224
+ if (err.status === 404) {
2225
+ console.error(err.message);
2226
+ process.exit(4);
2227
+ }
2228
+ if (err.status === 403 || err.status === 400 || err.status === 410 || err.status === 429) {
2229
+ console.error(err.message);
2230
+ process.exit(1);
2231
+ }
2232
+ }
2233
+ var msg = _instanceof(err, Error) ? err.message : String(err);
2234
+ console.error(msg);
2235
+ process.exit(1);
2236
+ }
1706
2237
  // --- mcp ---
1707
2238
  program.command('mcp').description('Start MCP server over stdin/stdout').action(function() {
1708
2239
  return _async_to_generator(function() {
@@ -27,6 +27,19 @@ function _async_to_generator(fn) {
27
27
  });
28
28
  };
29
29
  }
30
+ function _define_property(obj, key, value) {
31
+ if (key in obj) {
32
+ Object.defineProperty(obj, key, {
33
+ value: value,
34
+ enumerable: true,
35
+ configurable: true,
36
+ writable: true
37
+ });
38
+ } else {
39
+ obj[key] = value;
40
+ }
41
+ return obj;
42
+ }
30
43
  function _instanceof(left, right) {
31
44
  "@swc/helpers - instanceof";
32
45
  if (right != null && typeof Symbol !== "undefined" && right[Symbol.hasInstance]) {
@@ -35,6 +48,45 @@ function _instanceof(left, right) {
35
48
  return left instanceof right;
36
49
  }
37
50
  }
51
+ function _object_spread(target) {
52
+ for(var i = 1; i < arguments.length; i++){
53
+ var source = arguments[i] != null ? arguments[i] : {};
54
+ var ownKeys = Object.keys(source);
55
+ if (typeof Object.getOwnPropertySymbols === "function") {
56
+ ownKeys = ownKeys.concat(Object.getOwnPropertySymbols(source).filter(function(sym) {
57
+ return Object.getOwnPropertyDescriptor(source, sym).enumerable;
58
+ }));
59
+ }
60
+ ownKeys.forEach(function(key) {
61
+ _define_property(target, key, source[key]);
62
+ });
63
+ }
64
+ return target;
65
+ }
66
+ function ownKeys(object, enumerableOnly) {
67
+ var keys = Object.keys(object);
68
+ if (Object.getOwnPropertySymbols) {
69
+ var symbols = Object.getOwnPropertySymbols(object);
70
+ if (enumerableOnly) {
71
+ symbols = symbols.filter(function(sym) {
72
+ return Object.getOwnPropertyDescriptor(object, sym).enumerable;
73
+ });
74
+ }
75
+ keys.push.apply(keys, symbols);
76
+ }
77
+ return keys;
78
+ }
79
+ function _object_spread_props(target, source) {
80
+ source = source != null ? source : {};
81
+ if (Object.getOwnPropertyDescriptors) {
82
+ Object.defineProperties(target, Object.getOwnPropertyDescriptors(source));
83
+ } else {
84
+ ownKeys(Object(source)).forEach(function(key) {
85
+ Object.defineProperty(target, key, Object.getOwnPropertyDescriptor(source, key));
86
+ });
87
+ }
88
+ return target;
89
+ }
38
90
  function _ts_generator(thisArg, body) {
39
91
  var f, y, t, _ = {
40
92
  label: 0,
@@ -1060,4 +1112,446 @@ export function registerTools(server, api) {
1060
1112
  });
1061
1113
  })();
1062
1114
  });
1115
+ registerCommentTools(server, api);
1116
+ }
1117
+ /**
1118
+ * Comment tools (feat-comments §3) — stdio transport mirror of the
1119
+ * eight HTTP MCP tools in `api/src/mcp/comment-tools.ts`. KB-page
1120
+ * subjects return `subject_type_not_implemented` here too; the
1121
+ * polymorphic shape is part of the public contract so the CLI's MCP
1122
+ * surface accepts the same input even when the wire path 501s.
1123
+ */ function registerCommentTools(server, api) {
1124
+ function rejectKbPage() {
1125
+ return {
1126
+ content: [
1127
+ {
1128
+ type: 'text',
1129
+ text: JSON.stringify({
1130
+ error: 'subject_type_not_implemented',
1131
+ message: 'KB-page subjects are not yet supported. Pass subject_type="artifact".',
1132
+ status: 501
1133
+ })
1134
+ }
1135
+ ],
1136
+ isError: true
1137
+ };
1138
+ }
1139
+ function requireShortId(args) {
1140
+ if (!args.short_id) {
1141
+ return {
1142
+ content: [
1143
+ {
1144
+ type: 'text',
1145
+ text: JSON.stringify({
1146
+ error: 'validation_error',
1147
+ message: 'short_id is required for subject_type=artifact',
1148
+ status: 400
1149
+ })
1150
+ }
1151
+ ],
1152
+ isError: true
1153
+ };
1154
+ }
1155
+ return args.short_id;
1156
+ }
1157
+ var subjectArgs = {
1158
+ subject_type: z.enum([
1159
+ 'artifact',
1160
+ 'kb_page'
1161
+ ]).describe('Subject discriminator'),
1162
+ short_id: z.string().optional().describe('Artifact shortId (subject_type=artifact)'),
1163
+ kb_name: z.string().optional().describe('KB name (subject_type=kb_page; not yet supported)'),
1164
+ file_path: z.string().optional().describe('KB page path (subject_type=kb_page; not yet supported)')
1165
+ };
1166
+ var anchorSchema = z.object({
1167
+ textQuote: z.object({
1168
+ prefix: z.string(),
1169
+ exact: z.string(),
1170
+ suffix: z.string()
1171
+ }),
1172
+ cssPath: z.string(),
1173
+ textPosition: z.object({
1174
+ start: z.number().int(),
1175
+ end: z.number().int()
1176
+ }).optional()
1177
+ }).optional();
1178
+ server.tool('add_comment', 'Post a root comment or reply on an artifact. Root: pass `anchor` and omit `parent_id`. Reply: pass `parent_id` (the root comment id) and omit `anchor` (replies inherit the root anchor).', _object_spread_props(_object_spread({}, subjectArgs), {
1179
+ body: z.string().min(1).max(10000).describe('Comment body (≤10k chars)'),
1180
+ parent_id: z.string().optional().describe('Root comment id when posting a reply'),
1181
+ anchor: anchorSchema
1182
+ }), function(args) {
1183
+ return _async_to_generator(function() {
1184
+ var shortIdOrErr, result, err;
1185
+ return _ts_generator(this, function(_state) {
1186
+ switch(_state.label){
1187
+ case 0:
1188
+ if (args.subject_type === 'kb_page') {
1189
+ return [
1190
+ 2,
1191
+ rejectKbPage()
1192
+ ];
1193
+ }
1194
+ shortIdOrErr = requireShortId(args);
1195
+ if (typeof shortIdOrErr !== 'string') {
1196
+ return [
1197
+ 2,
1198
+ shortIdOrErr
1199
+ ];
1200
+ }
1201
+ _state.label = 1;
1202
+ case 1:
1203
+ _state.trys.push([
1204
+ 1,
1205
+ 3,
1206
+ ,
1207
+ 4
1208
+ ]);
1209
+ return [
1210
+ 4,
1211
+ api.addComment(shortIdOrErr, {
1212
+ body: args.body,
1213
+ anchor: args.anchor,
1214
+ parentId: args.parent_id
1215
+ })
1216
+ ];
1217
+ case 2:
1218
+ result = _state.sent();
1219
+ return [
1220
+ 2,
1221
+ okResponse(result)
1222
+ ];
1223
+ case 3:
1224
+ err = _state.sent();
1225
+ return [
1226
+ 2,
1227
+ errorResponse(err)
1228
+ ];
1229
+ case 4:
1230
+ return [
1231
+ 2
1232
+ ];
1233
+ }
1234
+ });
1235
+ })();
1236
+ });
1237
+ server.tool('list_comments', 'List comment threads on a subject. Reads from Postgres (not the KV widget cache).', _object_spread_props(_object_spread({}, subjectArgs), {
1238
+ status: z.enum([
1239
+ 'open',
1240
+ 'resolved',
1241
+ 'all'
1242
+ ]).optional().describe('Defaults to "open"'),
1243
+ since: z.string().optional().describe('ISO-8601 — return only threads with activity at or after this timestamp')
1244
+ }), function(args) {
1245
+ return _async_to_generator(function() {
1246
+ var shortIdOrErr, result, err;
1247
+ return _ts_generator(this, function(_state) {
1248
+ switch(_state.label){
1249
+ case 0:
1250
+ if (args.subject_type === 'kb_page') {
1251
+ return [
1252
+ 2,
1253
+ rejectKbPage()
1254
+ ];
1255
+ }
1256
+ shortIdOrErr = requireShortId(args);
1257
+ if (typeof shortIdOrErr !== 'string') {
1258
+ return [
1259
+ 2,
1260
+ shortIdOrErr
1261
+ ];
1262
+ }
1263
+ _state.label = 1;
1264
+ case 1:
1265
+ _state.trys.push([
1266
+ 1,
1267
+ 3,
1268
+ ,
1269
+ 4
1270
+ ]);
1271
+ return [
1272
+ 4,
1273
+ api.listComments(shortIdOrErr, {
1274
+ status: args.status,
1275
+ since: args.since
1276
+ })
1277
+ ];
1278
+ case 2:
1279
+ result = _state.sent();
1280
+ return [
1281
+ 2,
1282
+ okResponse(result)
1283
+ ];
1284
+ case 3:
1285
+ err = _state.sent();
1286
+ return [
1287
+ 2,
1288
+ errorResponse(err)
1289
+ ];
1290
+ case 4:
1291
+ return [
1292
+ 2
1293
+ ];
1294
+ }
1295
+ });
1296
+ })();
1297
+ });
1298
+ server.tool('edit_comment', 'Edit your own comment within the 5-minute author window. After 5 minutes the body is locked.', {
1299
+ comment_id: z.string(),
1300
+ body: z.string().min(1).max(10000)
1301
+ }, function(args) {
1302
+ return _async_to_generator(function() {
1303
+ var result, err;
1304
+ return _ts_generator(this, function(_state) {
1305
+ switch(_state.label){
1306
+ case 0:
1307
+ _state.trys.push([
1308
+ 0,
1309
+ 2,
1310
+ ,
1311
+ 3
1312
+ ]);
1313
+ return [
1314
+ 4,
1315
+ api.editComment(args.comment_id, args.body)
1316
+ ];
1317
+ case 1:
1318
+ result = _state.sent();
1319
+ return [
1320
+ 2,
1321
+ okResponse(result)
1322
+ ];
1323
+ case 2:
1324
+ err = _state.sent();
1325
+ return [
1326
+ 2,
1327
+ errorResponse(err)
1328
+ ];
1329
+ case 3:
1330
+ return [
1331
+ 2
1332
+ ];
1333
+ }
1334
+ });
1335
+ })();
1336
+ });
1337
+ server.tool('delete_comment', 'Soft-delete a comment. Author / artifact creator / org admin. Replies remain visible; body becomes "[deleted]".', {
1338
+ comment_id: z.string()
1339
+ }, function(args) {
1340
+ return _async_to_generator(function() {
1341
+ var err;
1342
+ return _ts_generator(this, function(_state) {
1343
+ switch(_state.label){
1344
+ case 0:
1345
+ _state.trys.push([
1346
+ 0,
1347
+ 2,
1348
+ ,
1349
+ 3
1350
+ ]);
1351
+ return [
1352
+ 4,
1353
+ api.deleteComment(args.comment_id)
1354
+ ];
1355
+ case 1:
1356
+ _state.sent();
1357
+ return [
1358
+ 2,
1359
+ okResponse({
1360
+ deleted: true
1361
+ })
1362
+ ];
1363
+ case 2:
1364
+ err = _state.sent();
1365
+ return [
1366
+ 2,
1367
+ errorResponse(err)
1368
+ ];
1369
+ case 3:
1370
+ return [
1371
+ 2
1372
+ ];
1373
+ }
1374
+ });
1375
+ })();
1376
+ });
1377
+ server.tool('resolve_thread', 'Mark a thread resolved (root comment id). Thread participant / artifact creator / org admin.', {
1378
+ comment_id: z.string()
1379
+ }, function(args) {
1380
+ return _async_to_generator(function() {
1381
+ var result, err;
1382
+ return _ts_generator(this, function(_state) {
1383
+ switch(_state.label){
1384
+ case 0:
1385
+ _state.trys.push([
1386
+ 0,
1387
+ 2,
1388
+ ,
1389
+ 3
1390
+ ]);
1391
+ return [
1392
+ 4,
1393
+ api.resolveThread(args.comment_id)
1394
+ ];
1395
+ case 1:
1396
+ result = _state.sent();
1397
+ return [
1398
+ 2,
1399
+ okResponse(result)
1400
+ ];
1401
+ case 2:
1402
+ err = _state.sent();
1403
+ return [
1404
+ 2,
1405
+ errorResponse(err)
1406
+ ];
1407
+ case 3:
1408
+ return [
1409
+ 2
1410
+ ];
1411
+ }
1412
+ });
1413
+ })();
1414
+ });
1415
+ server.tool('reopen_thread', 'Reopen a resolved thread. Any authenticated user with view access on the artifact.', {
1416
+ comment_id: z.string()
1417
+ }, function(args) {
1418
+ return _async_to_generator(function() {
1419
+ var result, err;
1420
+ return _ts_generator(this, function(_state) {
1421
+ switch(_state.label){
1422
+ case 0:
1423
+ _state.trys.push([
1424
+ 0,
1425
+ 2,
1426
+ ,
1427
+ 3
1428
+ ]);
1429
+ return [
1430
+ 4,
1431
+ api.reopenThread(args.comment_id)
1432
+ ];
1433
+ case 1:
1434
+ result = _state.sent();
1435
+ return [
1436
+ 2,
1437
+ okResponse(result)
1438
+ ];
1439
+ case 2:
1440
+ err = _state.sent();
1441
+ return [
1442
+ 2,
1443
+ errorResponse(err)
1444
+ ];
1445
+ case 3:
1446
+ return [
1447
+ 2
1448
+ ];
1449
+ }
1450
+ });
1451
+ })();
1452
+ });
1453
+ server.tool('watch', 'Watch the subject for comment notifications. Per-user; service-account API keys cannot subscribe.', subjectArgs, function(args) {
1454
+ return _async_to_generator(function() {
1455
+ var shortIdOrErr, result, err;
1456
+ return _ts_generator(this, function(_state) {
1457
+ switch(_state.label){
1458
+ case 0:
1459
+ if (args.subject_type === 'kb_page') {
1460
+ return [
1461
+ 2,
1462
+ rejectKbPage()
1463
+ ];
1464
+ }
1465
+ shortIdOrErr = requireShortId(args);
1466
+ if (typeof shortIdOrErr !== 'string') {
1467
+ return [
1468
+ 2,
1469
+ shortIdOrErr
1470
+ ];
1471
+ }
1472
+ _state.label = 1;
1473
+ case 1:
1474
+ _state.trys.push([
1475
+ 1,
1476
+ 3,
1477
+ ,
1478
+ 4
1479
+ ]);
1480
+ return [
1481
+ 4,
1482
+ api.watchArtifact(shortIdOrErr)
1483
+ ];
1484
+ case 2:
1485
+ result = _state.sent();
1486
+ return [
1487
+ 2,
1488
+ okResponse(result)
1489
+ ];
1490
+ case 3:
1491
+ err = _state.sent();
1492
+ return [
1493
+ 2,
1494
+ errorResponse(err)
1495
+ ];
1496
+ case 4:
1497
+ return [
1498
+ 2
1499
+ ];
1500
+ }
1501
+ });
1502
+ })();
1503
+ });
1504
+ server.tool('unwatch', 'Unwatch the subject. Per-user; service-account API keys cannot subscribe.', subjectArgs, function(args) {
1505
+ return _async_to_generator(function() {
1506
+ var shortIdOrErr, err;
1507
+ return _ts_generator(this, function(_state) {
1508
+ switch(_state.label){
1509
+ case 0:
1510
+ if (args.subject_type === 'kb_page') {
1511
+ return [
1512
+ 2,
1513
+ rejectKbPage()
1514
+ ];
1515
+ }
1516
+ shortIdOrErr = requireShortId(args);
1517
+ if (typeof shortIdOrErr !== 'string') {
1518
+ return [
1519
+ 2,
1520
+ shortIdOrErr
1521
+ ];
1522
+ }
1523
+ _state.label = 1;
1524
+ case 1:
1525
+ _state.trys.push([
1526
+ 1,
1527
+ 3,
1528
+ ,
1529
+ 4
1530
+ ]);
1531
+ return [
1532
+ 4,
1533
+ api.unwatchArtifact(shortIdOrErr)
1534
+ ];
1535
+ case 2:
1536
+ _state.sent();
1537
+ return [
1538
+ 2,
1539
+ okResponse({
1540
+ watching: false
1541
+ })
1542
+ ];
1543
+ case 3:
1544
+ err = _state.sent();
1545
+ return [
1546
+ 2,
1547
+ errorResponse(err)
1548
+ ];
1549
+ case 4:
1550
+ return [
1551
+ 2
1552
+ ];
1553
+ }
1554
+ });
1555
+ })();
1556
+ });
1063
1557
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@displaydev/cli",
3
- "version": "0.18.0",
3
+ "version": "0.19.0",
4
4
  "type": "module",
5
5
  "bin": {
6
6
  "dsp": "dist/main.js"