@chatcode/cco-market 1.45.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (177) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +146 -0
  3. package/README.zh.md +143 -0
  4. package/UPDATE-API-V1.md +132 -0
  5. package/client/client.js +11534 -0
  6. package/cordis.patch.yml +5 -0
  7. package/lib/accelerate.js +184 -0
  8. package/lib/agents.js +36 -0
  9. package/lib/backup.js +572 -0
  10. package/lib/catalog-local-match.js +126 -0
  11. package/lib/catalog-npm.js +111 -0
  12. package/lib/changelog.js +242 -0
  13. package/lib/channels.js +64 -0
  14. package/lib/check.js +1067 -0
  15. package/lib/compatibility.js +198 -0
  16. package/lib/diagnostics.js +49 -0
  17. package/lib/discovery-compatibility.js +260 -0
  18. package/lib/dsh-cli.js +949 -0
  19. package/lib/dsh-install.js +108 -0
  20. package/lib/gist.js +352 -0
  21. package/lib/groups.js +97 -0
  22. package/lib/home-paths.js +42 -0
  23. package/lib/hot.js +519 -0
  24. package/lib/http.js +39 -0
  25. package/lib/index.js +97 -0
  26. package/lib/install.js +387 -0
  27. package/lib/log.js +197 -0
  28. package/lib/ndjson.js +154 -0
  29. package/lib/net.js +98 -0
  30. package/lib/order.js +284 -0
  31. package/lib/patch.js +521 -0
  32. package/lib/pnpm-compat.js +490 -0
  33. package/lib/presets.js +278 -0
  34. package/lib/profile.js +911 -0
  35. package/lib/region-probe.js +93 -0
  36. package/lib/regions.js +253 -0
  37. package/lib/registry.js +204 -0
  38. package/lib/restart.js +373 -0
  39. package/lib/routes.js +4372 -0
  40. package/lib/settings.js +109 -0
  41. package/lib/skill-market/api.js +119 -0
  42. package/lib/skill-market/config.js +29 -0
  43. package/lib/skill-market/installer.js +352 -0
  44. package/lib/skill-market/runtime.js +13 -0
  45. package/lib/skill-market/tui.js +119 -0
  46. package/lib/skill-market/types.js +1 -0
  47. package/lib/skill-market/web-routes.js +123 -0
  48. package/lib/snapshot.js +500 -0
  49. package/lib/source-migration.js +54 -0
  50. package/lib/sources.js +596 -0
  51. package/lib/store.js +91 -0
  52. package/lib/themes.js +102 -0
  53. package/lib/trial.js +116 -0
  54. package/lib/types/accelerate.d.ts +85 -0
  55. package/lib/types/agents.d.ts +22 -0
  56. package/lib/types/backup.d.ts +131 -0
  57. package/lib/types/catalog-local-match.d.ts +50 -0
  58. package/lib/types/catalog-npm.d.ts +47 -0
  59. package/lib/types/changelog.d.ts +102 -0
  60. package/lib/types/channels.d.ts +56 -0
  61. package/lib/types/check.d.ts +266 -0
  62. package/lib/types/compatibility.d.ts +64 -0
  63. package/lib/types/diagnostics.d.ts +29 -0
  64. package/lib/types/discovery-compatibility.d.ts +80 -0
  65. package/lib/types/dsh-cli.d.ts +324 -0
  66. package/lib/types/dsh-install.d.ts +46 -0
  67. package/lib/types/gist.d.ts +53 -0
  68. package/lib/types/groups.d.ts +34 -0
  69. package/lib/types/home-paths.d.ts +16 -0
  70. package/lib/types/hot.d.ts +221 -0
  71. package/lib/types/http.d.ts +12 -0
  72. package/lib/types/index.d.ts +14 -0
  73. package/lib/types/install.d.ts +172 -0
  74. package/lib/types/log.d.ts +43 -0
  75. package/lib/types/ndjson.d.ts +52 -0
  76. package/lib/types/net.d.ts +58 -0
  77. package/lib/types/order.d.ts +100 -0
  78. package/lib/types/patch.d.ts +129 -0
  79. package/lib/types/pnpm-compat.d.ts +93 -0
  80. package/lib/types/presets.d.ts +90 -0
  81. package/lib/types/profile.d.ts +253 -0
  82. package/lib/types/region-probe.d.ts +50 -0
  83. package/lib/types/regions.d.ts +122 -0
  84. package/lib/types/registry.d.ts +86 -0
  85. package/lib/types/restart.d.ts +194 -0
  86. package/lib/types/routes.d.ts +67 -0
  87. package/lib/types/settings.d.ts +78 -0
  88. package/lib/types/skill-market/api.d.ts +10 -0
  89. package/lib/types/skill-market/config.d.ts +3 -0
  90. package/lib/types/skill-market/installer.d.ts +23 -0
  91. package/lib/types/skill-market/runtime.d.ts +10 -0
  92. package/lib/types/skill-market/tui.d.ts +4 -0
  93. package/lib/types/skill-market/types.d.ts +71 -0
  94. package/lib/types/skill-market/web-routes.d.ts +19 -0
  95. package/lib/types/snapshot.d.ts +93 -0
  96. package/lib/types/source-migration.d.ts +11 -0
  97. package/lib/types/sources.d.ts +216 -0
  98. package/lib/types/store.d.ts +30 -0
  99. package/lib/types/themes.d.ts +40 -0
  100. package/lib/types/trial.d.ts +61 -0
  101. package/lib/types/update-api-v1.d.ts +66 -0
  102. package/lib/types/updates.d.ts +123 -0
  103. package/lib/types/verify.d.ts +139 -0
  104. package/lib/update-api-v1.js +215 -0
  105. package/lib/updates.js +361 -0
  106. package/lib/verify.js +453 -0
  107. package/package.json +121 -0
  108. package/src/accelerate.ts +213 -0
  109. package/src/agents.ts +43 -0
  110. package/src/backup.ts +583 -0
  111. package/src/catalog-local-match.ts +144 -0
  112. package/src/catalog-npm.ts +120 -0
  113. package/src/changelog.ts +282 -0
  114. package/src/channels.ts +70 -0
  115. package/src/check.ts +1239 -0
  116. package/src/client/CommentsModal.tsx +119 -0
  117. package/src/client/Diagnostics.tsx +907 -0
  118. package/src/client/ErrorBoundary.tsx +111 -0
  119. package/src/client/InstallToast.tsx +31 -0
  120. package/src/client/Market.module.css +830 -0
  121. package/src/client/MarketSection.tsx +5301 -0
  122. package/src/client/OperationsPanel.tsx +365 -0
  123. package/src/client/SettingsCard.tsx +621 -0
  124. package/src/client/SkillMarket.module.css +21 -0
  125. package/src/client/SkillMarketSection.tsx +162 -0
  126. package/src/client/comments.ts +54 -0
  127. package/src/client/globals.d.ts +13 -0
  128. package/src/client/index.ts +180 -0
  129. package/src/client/locales.ts +1112 -0
  130. package/src/client/market-data.ts +1321 -0
  131. package/src/client/operations.ts +201 -0
  132. package/src/client/preset-panel.tsx +263 -0
  133. package/src/client/primitives.d.ts +140 -0
  134. package/src/client/self-check.ts +147 -0
  135. package/src/client/snapshot-panel.tsx +244 -0
  136. package/src/compatibility.ts +237 -0
  137. package/src/diagnostics.ts +84 -0
  138. package/src/discovery-compatibility.ts +315 -0
  139. package/src/dsh-cli.ts +1126 -0
  140. package/src/dsh-install.ts +118 -0
  141. package/src/gist.ts +362 -0
  142. package/src/groups.ts +111 -0
  143. package/src/home-paths.ts +53 -0
  144. package/src/hot.ts +628 -0
  145. package/src/http.ts +41 -0
  146. package/src/index.ts +128 -0
  147. package/src/install.ts +420 -0
  148. package/src/log.ts +206 -0
  149. package/src/ndjson.ts +185 -0
  150. package/src/net.ts +106 -0
  151. package/src/order.ts +303 -0
  152. package/src/patch.ts +522 -0
  153. package/src/pnpm-compat.ts +527 -0
  154. package/src/presets.ts +344 -0
  155. package/src/profile.ts +940 -0
  156. package/src/region-probe.ts +97 -0
  157. package/src/regions.ts +310 -0
  158. package/src/registry.ts +250 -0
  159. package/src/restart.ts +396 -0
  160. package/src/routes.ts +4506 -0
  161. package/src/settings.ts +141 -0
  162. package/src/skill-market/api.ts +130 -0
  163. package/src/skill-market/config.ts +32 -0
  164. package/src/skill-market/installer.ts +337 -0
  165. package/src/skill-market/runtime.ts +14 -0
  166. package/src/skill-market/tui.ts +157 -0
  167. package/src/skill-market/types.ts +80 -0
  168. package/src/skill-market/web-routes.ts +132 -0
  169. package/src/snapshot.ts +532 -0
  170. package/src/source-migration.ts +61 -0
  171. package/src/sources.ts +565 -0
  172. package/src/store.ts +89 -0
  173. package/src/themes.ts +125 -0
  174. package/src/trial.ts +156 -0
  175. package/src/update-api-v1.ts +277 -0
  176. package/src/updates.ts +400 -0
  177. package/src/verify.ts +492 -0
@@ -0,0 +1,5 @@
1
+ # dsh bundle patch: inserts this plugin into a profile's layer stack.
2
+ - insert:
3
+ - id: dsh-market
4
+ name: '@chatcode/cco-market'
5
+ disabled: !!js process.title === 'dsh-webworker'
@@ -0,0 +1,184 @@
1
+ /**
2
+ * Resolving a GitHub install through a region's proxy without proxying the
3
+ * tarball pnpm records.
4
+ *
5
+ * pnpm does not fetch `github:owner/repo` with `git clone`; it resolves the
6
+ * shortcut and downloads a tarball from codeload.github.com. That rules out
7
+ * the usual `git config insteadOf` trick — there is no git command to
8
+ * redirect.
9
+ *
10
+ * Prefix-proxying that tarball used to save substantial time, but pnpm 11's
11
+ * fail-closed lockfile checks changed the safety boundary. A URL shaped like
12
+ * `https://proxy/https://codeload.github.com/.../<commit>` no longer has the
13
+ * codeload hostname, so pnpm treats it as an ordinary remote tarball and
14
+ * requires an integrity hash that its GitHub resolver does not write. The
15
+ * result is ERR_PNPM_MISSING_TARBALL_INTEGRITY on the install itself (#385).
16
+ * Disabling that check or minting a checksum from whatever the proxy served
17
+ * would weaken pnpm's supply-chain protection, so neither is acceptable.
18
+ *
19
+ * The safe middle ground is to resolve HEAD through the regional proxy, then
20
+ * hand pnpm a commit-pinned `github:owner/repo#<sha>` target. The ref lookup
21
+ * still avoids a slow or unreachable GitHub metadata request; pnpm itself
22
+ * fetches the canonical codeload URL, records it as `gitHosted: true`, and
23
+ * keeps its integrity policy intact.
24
+ *
25
+ * - **The commit has to be pinned.** The profile reads each plugin's
26
+ * installed commit back out of the lockfile by matching a codeload URL
27
+ * ending in a 40-character SHA (src/profile.ts). A `HEAD` tarball installs
28
+ * perfectly and then reports no version forever. So this resolves the SHA
29
+ * first, and a rewrite that cannot get one does not happen.
30
+ * - **Build-script approval has to keep matching.** `gitAllowBuildsKey`
31
+ * (src/sources.ts) derives its stable key from the repo, and the pinned
32
+ * GitHub form preserves that identity.
33
+ *
34
+ * Catalog subpath entries are left alone: `#path:` identifies a different
35
+ * package inside the repo, so the acceleration step never rewrites that
36
+ * fragment. Collection roots discovered after install preserve the resolved
37
+ * commit and add their subpath as pnpm's second `&path:` selector.
38
+ *
39
+ * Every SHA-lookup failure falls back to the original target. Acceleration
40
+ * is an optimisation, and an optimisation that can fail an install is a bug.
41
+ */
42
+ import { logEvent } from './log.js';
43
+ import { marketFetch } from './net.js';
44
+ import { githubRoutesFor, rememberGithubRoute, routesFor, throughProxy, } from './regions.js';
45
+ /** A bare repo shortcut whose HEAD can be replaced by one immutable ref. */
46
+ const BARE_GITHUB_RE = /^github:([A-Za-z0-9_.-]+\/[A-Za-z0-9_.-]+)$/;
47
+ /**
48
+ * How long to wait for the SHA before giving up and installing directly.
49
+ *
50
+ * Short on purpose: this is spent BEFORE the download starts, and the whole
51
+ * point is to avoid a slow or unreachable direct metadata lookup. A proxy
52
+ * that cannot answer promptly should not delay pnpm's ordinary direct path.
53
+ */
54
+ const RESOLVE_TIMEOUT_MS = 6000;
55
+ /**
56
+ * The commit `HEAD` points at, from git's own ref advertisement.
57
+ *
58
+ * This is the endpoint `git clone` reads before it fetches anything, and it
59
+ * is the right one here for two measured reasons. It is not the REST API, so
60
+ * it does not consume the 60-requests-per-hour unauthenticated quota that a
61
+ * user installing a handful of plugins could plausibly exhaust. And it
62
+ * survives the proxy: over five consecutive tries from an unproxied mainland
63
+ * connection it answered 200 in ~1.2s every time, while the REST API through
64
+ * the same proxy returned 200, 200, then 403 — a proxy that rate-limits the
65
+ * API path would silently drop every install back to the slow route.
66
+ *
67
+ * The response is git's pkt-line format, whose first ref line carries
68
+ * `<sha> HEAD\0<capabilities>`. Read with a pattern rather than a parser:
69
+ * one 40-character hex string followed by `HEAD` is unambiguous in this
70
+ * payload, and a length-prefix reader would be more code to get wrong.
71
+ *
72
+ * The same advertisement lists every branch and tag, which is what `ref`
73
+ * uses. A plugin installed from `github:owner/repo#publish` is not asking
74
+ * about the default branch at all, and answering with it made the market
75
+ * report an update forever (#446) — the two SHAs simply never match. Both
76
+ * namespaces are searched because pnpm accepts a tag there too, branches
77
+ * first since that is what the reports are about.
78
+ * @param ref - branch or tag to resolve, or undefined for the default branch.
79
+ */
80
+ export async function headCommit(repo, proxy, signal, ref) {
81
+ const result = await tryHeadCommit(repo, proxy, signal, ref);
82
+ return result.kind === 'valid' ? result.sha : null;
83
+ }
84
+ /** One route attempt, preserving valid "ref is absent" from invalid payloads. */
85
+ async function tryHeadCommit(repo, proxy, signal, ref) {
86
+ const base = `https://github.com/${repo}/info/refs?service=git-upload-pack`;
87
+ try {
88
+ const res = await marketFetch(throughProxy(proxy, base), {
89
+ signal,
90
+ headers: { 'user-agent': 'git/2.40.0' },
91
+ });
92
+ if (!res.ok)
93
+ return { kind: 'failed' };
94
+ const body = await res.text();
95
+ const contentType = res
96
+ .headers?.get?.('content-type')?.toLowerCase() ?? '';
97
+ // Public mirrors often answer a failed upstream request with their own
98
+ // branded HTML and status 200. A git advertisement has both its service
99
+ // prelude and at least one advertised ref; accepting anything else would
100
+ // cache a route that never returned Git data in the first place.
101
+ if (contentType.includes('text/html')
102
+ || !body.includes('# service=git-upload-pack')
103
+ || !/[0-9a-f]{40} (?:HEAD|refs\/(?:heads|tags)\/)/u.test(body)) {
104
+ return { kind: 'failed' };
105
+ }
106
+ if (ref === undefined) {
107
+ const found = /([0-9a-f]{40}) HEAD/.exec(body);
108
+ return { kind: 'valid', sha: found === null ? null : found[1] };
109
+ }
110
+ // Anchored to the ref's full name so `publish` cannot match a branch
111
+ // called `publish-old`, and escaped because a ref may contain regex
112
+ // metacharacters (`.` is legal in a branch name).
113
+ const quoted = ref.replace(/[.*+?^${}()|[\]\\]/gu, String.raw `\$&`);
114
+ for (const namespace of ['heads', 'tags']) {
115
+ const found = new RegExp(String.raw `([0-9a-f]{40}) refs/${namespace}/${quoted}(?![^\s])`, 'u').exec(body);
116
+ if (found !== null)
117
+ return { kind: 'valid', sha: found[1] };
118
+ }
119
+ // The advertisement is authoritative for this repository. Asking another
120
+ // mirror cannot make a branch that is absent here appear.
121
+ return { kind: 'valid', sha: null };
122
+ }
123
+ catch {
124
+ return { kind: 'failed' };
125
+ }
126
+ }
127
+ /** Run one candidate under its own budget, optionally linked to a caller signal. */
128
+ async function timedHeadCommit(repo, route, ref, signal) {
129
+ const controller = new AbortController();
130
+ const abort = () => { controller.abort(); };
131
+ if (signal?.aborted === true)
132
+ controller.abort();
133
+ else
134
+ signal?.addEventListener('abort', abort, { once: true });
135
+ const timer = setTimeout(abort, RESOLVE_TIMEOUT_MS);
136
+ try {
137
+ return await tryHeadCommit(repo, route, controller.signal, ref);
138
+ }
139
+ finally {
140
+ clearTimeout(timer);
141
+ signal?.removeEventListener('abort', abort);
142
+ }
143
+ }
144
+ /**
145
+ * The current `HEAD` commit for a repo, on whichever route the region uses.
146
+ *
147
+ * Wraps the timeout so callers outside the install path — the build-script
148
+ * approval below, which needs a commit-pinned key — do not each reinvent it.
149
+ */
150
+ export async function resolveHeadCommit(repo, region, env = process.env, ref) {
151
+ for (const route of githubRoutesFor('git', region, env)) {
152
+ const result = await timedHeadCommit(repo, route, ref);
153
+ if (result.kind === 'failed')
154
+ continue;
155
+ rememberGithubRoute('git', route);
156
+ return result.sha;
157
+ }
158
+ return null;
159
+ }
160
+ /**
161
+ * The install target to actually hand pnpm, given the region in force.
162
+ *
163
+ * @param target - what `installTargetFor` produced.
164
+ * @param region - the download region.
165
+ * @param env - environment, for the proxy override.
166
+ * @returns a commit-pinned GitHub shortcut when one route resolves HEAD,
167
+ * otherwise `target` unchanged.
168
+ */
169
+ export async function acceleratedTarget(target, region, env = process.env) {
170
+ // A plain global install lets pnpm do its ordinary GitHub resolution. A
171
+ // custom prefix makes even that region an accelerated one.
172
+ if (routesFor(region, env).githubProxy === null)
173
+ return target;
174
+ const bare = BARE_GITHUB_RE.exec(target);
175
+ if (bare === null)
176
+ return target;
177
+ const repo = bare[1];
178
+ const sha = await resolveHeadCommit(repo, region, env);
179
+ if (sha === null) {
180
+ logEvent('info', 'region', `${repo}: could not resolve a commit through the available routes; installing directly`);
181
+ return target;
182
+ }
183
+ return `github:${repo}#${sha}`;
184
+ }
package/lib/agents.js ADDED
@@ -0,0 +1,36 @@
1
+ /**
2
+ * Optional host-provided agent inventory: lets the market refuse plugin
3
+ * mutations while a live agent is mid-turn. Mutating `node_modules` under a
4
+ * running agent replaces files the running plugin modules may still read or
5
+ * lazily import — the update "succeeds" while old code and new files mix.
6
+ */
7
+ /**
8
+ * Ids of the host's currently running agents, or [] when the host has no
9
+ * agents service. Only a positive `status === 'running'` blocks an update —
10
+ * unknown statuses are treated as not running, so a future agent
11
+ * implementation with different wording fails open (the market stays
12
+ * usable) instead of wedging the plugin page.
13
+ */
14
+ export function runningAgentIds(agents) {
15
+ if (agents === undefined)
16
+ return [];
17
+ let listed;
18
+ try {
19
+ listed = agents.list();
20
+ }
21
+ catch {
22
+ // A half-disposed registry must never take the market's routes down.
23
+ return [];
24
+ }
25
+ if (!Array.isArray(listed))
26
+ return [];
27
+ const ids = [];
28
+ for (const agent of listed) {
29
+ if (agent === null || typeof agent !== 'object' || agent.status !== 'running')
30
+ continue;
31
+ const id = typeof agent.id === 'string' && agent.id !== '' ? agent.id : 'agent';
32
+ if (!ids.includes(id))
33
+ ids.push(id);
34
+ }
35
+ return ids;
36
+ }