@displaydev/cli 0.17.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.
package/dist/main.js CHANGED
@@ -726,11 +726,24 @@ program.command('rename <shortId>').description('Rename a published artifact. Sl
726
726
  })();
727
727
  });
728
728
  // --- find ---
729
- program.command('find [query]').description('Search for artifacts').option('--by <email>', 'Filter by publisher email').option('--mine', 'Show only artifacts you published').option('--since <date>', 'Filter by date (ISO format)').option('--sort <col>', 'Sort column: updated_at, view_count, name', 'updated_at').option('--dir <direction>', 'Sort direction: asc or desc').option('--limit <n>', 'Max rows to fetch (1-100)', function(v) {
729
+ function collectAuthor(value, prev) {
730
+ return prev.concat(value);
731
+ }
732
+ function parseVisibilityCsv(raw) {
733
+ return raw.split(',').map(function(v) {
734
+ return v.trim();
735
+ }).filter(Boolean);
736
+ }
737
+ var VISIBILITY_VALUES = new Set([
738
+ 'public',
739
+ 'company',
740
+ 'private'
741
+ ]);
742
+ program.command('find [query]').alias('list').description('List or search artifacts. Omit [query] to list every artifact (paginated).').option('--author <a>', 'Filter by author (repeatable). Each value: email, userId, or "me".', collectAuthor, []).option('--visibility <list>', 'CSV of visibility levels: public, company, private. "private" returns only your own.').option('--since <date>', 'Filter by updated since ISO date').option('--sort <col>', 'Sort column: updated_at, view_count, name').option('--dir <direction>', 'Sort direction: asc or desc').option('--cursor <token>', 'Opaque pagination token from a prior response. Drop the cursor when filters change — the wire only validates it against sort/dir, so reusing it after changing --author / --visibility / --since / [query] silently skews results.').option('--limit <n>', 'Max rows to fetch (1-100)', function(v) {
730
743
  return parseInt(v, 10);
731
744
  }).action(function(query, opts) {
732
745
  return _async_to_generator(function() {
733
- var auth, client, results, _iteratorNormalCompletion, _didIteratorError, _iteratorError, _iterator, _step, a;
746
+ var visibility, tokens, _iteratorNormalCompletion, _didIteratorError, _iteratorError, _iterator, _step, v, auth, client, response, err, msg, data, nextCursor, totalCount, _iteratorNormalCompletion1, _didIteratorError1, _iteratorError1, _iterator1, _step1, a;
734
747
  return _ts_generator(this, function(_state) {
735
748
  switch(_state.label){
736
749
  case 0:
@@ -746,53 +759,126 @@ program.command('find [query]').description('Search for artifacts').option('--by
746
759
  console.error("Invalid --dir: ".concat(opts.dir, ". Use asc or desc."));
747
760
  process.exit(1);
748
761
  }
762
+ if (opts.visibility) {
763
+ tokens = parseVisibilityCsv(opts.visibility);
764
+ _iteratorNormalCompletion = true, _didIteratorError = false, _iteratorError = undefined;
765
+ try {
766
+ for(_iterator = tokens[Symbol.iterator](); !(_iteratorNormalCompletion = (_step = _iterator.next()).done); _iteratorNormalCompletion = true){
767
+ v = _step.value;
768
+ if (!VISIBILITY_VALUES.has(v)) {
769
+ console.error("Invalid --visibility: ".concat(v, ". Use public, company, or private."));
770
+ process.exit(1);
771
+ }
772
+ }
773
+ } catch (err) {
774
+ _didIteratorError = true;
775
+ _iteratorError = err;
776
+ } finally{
777
+ try {
778
+ if (!_iteratorNormalCompletion && _iterator.return != null) {
779
+ _iterator.return();
780
+ }
781
+ } finally{
782
+ if (_didIteratorError) {
783
+ throw _iteratorError;
784
+ }
785
+ }
786
+ }
787
+ visibility = tokens;
788
+ }
749
789
  return [
750
790
  4,
751
791
  resolveAuthOrConfig()
752
792
  ];
753
793
  case 1:
754
794
  auth = _state.sent();
795
+ // The wire silently drops `me` when authenticated with an org API key (no
796
+ // session user → caller id is null in resolveAuthorIds). Catch that at the
797
+ // command layer so the user gets an explicit failure rather than an
798
+ // unfiltered list. Trim each value to mirror the wire — it trims tokens
799
+ // before resolving `me`, so `--author ' me '` would otherwise bypass the
800
+ // guard and re-introduce the silent-broaden bug.
801
+ if (auth.keyType === 'org' && opts.author.some(function(a) {
802
+ return a.trim() === 'me';
803
+ })) {
804
+ console.error('--author me requires a user-scoped credential. Use a user API key or sign in via dashboard.');
805
+ process.exit(1);
806
+ }
755
807
  client = createClient(auth);
808
+ _state.label = 2;
809
+ case 2:
810
+ _state.trys.push([
811
+ 2,
812
+ 4,
813
+ ,
814
+ 5
815
+ ]);
756
816
  return [
757
817
  4,
758
818
  client.find({
759
819
  query: query,
760
- publishedBy: opts.by,
761
- mine: opts.mine,
820
+ author: opts.author.length > 0 ? opts.author : undefined,
821
+ visibility: visibility,
762
822
  since: opts.since,
763
823
  sort: opts.sort,
764
824
  dir: opts.dir,
825
+ cursor: opts.cursor,
765
826
  limit: opts.limit
766
827
  })
767
828
  ];
768
- case 2:
769
- results = _state.sent();
770
- if (results.length === 0) {
829
+ case 3:
830
+ response = _state.sent();
831
+ return [
832
+ 3,
833
+ 5
834
+ ];
835
+ case 4:
836
+ err = _state.sent();
837
+ msg = _instanceof(err, Error) ? err.message : String(err);
838
+ console.error(msg);
839
+ process.exit(1);
840
+ return [
841
+ 3,
842
+ 5
843
+ ];
844
+ case 5:
845
+ data = response.data, nextCursor = response.nextCursor, totalCount = response.totalCount;
846
+ if (data.length === 0) {
771
847
  console.log('No artifacts found.');
772
848
  return [
773
849
  2
774
850
  ];
775
851
  }
776
- _iteratorNormalCompletion = true, _didIteratorError = false, _iteratorError = undefined;
852
+ _iteratorNormalCompletion1 = true, _didIteratorError1 = false, _iteratorError1 = undefined;
777
853
  try {
778
- for(_iterator = results[Symbol.iterator](); !(_iteratorNormalCompletion = (_step = _iterator.next()).done); _iteratorNormalCompletion = true){
779
- a = _step.value;
854
+ for(_iterator1 = data[Symbol.iterator](); !(_iteratorNormalCompletion1 = (_step1 = _iterator1.next()).done); _iteratorNormalCompletion1 = true){
855
+ a = _step1.value;
780
856
  console.log("".concat(a.shortId, " v").concat(a.currentVersion, " ").concat(a.name, " ").concat(a.url));
781
857
  }
782
858
  } catch (err) {
783
- _didIteratorError = true;
784
- _iteratorError = err;
859
+ _didIteratorError1 = true;
860
+ _iteratorError1 = err;
785
861
  } finally{
786
862
  try {
787
- if (!_iteratorNormalCompletion && _iterator.return != null) {
788
- _iterator.return();
863
+ if (!_iteratorNormalCompletion1 && _iterator1.return != null) {
864
+ _iterator1.return();
789
865
  }
790
866
  } finally{
791
- if (_didIteratorError) {
792
- throw _iteratorError;
867
+ if (_didIteratorError1) {
868
+ throw _iteratorError1;
793
869
  }
794
870
  }
795
871
  }
872
+ // Footer on stderr so pipe consumers (`dsp find | xargs ...`) get clean
873
+ // stdout. Order: count line first, then the next-page hint.
874
+ if (totalCount === -1) {
875
+ process.stderr.write("Showing ".concat(data.length, " matching artifacts (count exceeded the budget; rerun with a tighter filter to get an exact total).\n"));
876
+ } else if (totalCount >= 0) {
877
+ process.stderr.write("Showing ".concat(data.length, "/").concat(totalCount, " matching artifacts.\n"));
878
+ }
879
+ if (nextCursor !== null) {
880
+ process.stderr.write("More results available. Re-run with --cursor ".concat(nextCursor, " to fetch the next page.\n"));
881
+ }
796
882
  return [
797
883
  2
798
884
  ];
@@ -1617,6 +1703,537 @@ program.command('clear-logo').description('Remove the org logo (idempotent — s
1617
1703
  });
1618
1704
  })();
1619
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
+ }
1620
2237
  // --- mcp ---
1621
2238
  program.command('mcp').description('Start MCP server over stdin/stdout').action(function() {
1622
2239
  return _async_to_generator(function() {