@linxiraos/pi-wire 1.1.19 → 1.1.22

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/CHANGELOG.md CHANGED
@@ -2,6 +2,10 @@
2
2
 
3
3
  ## [Unreleased]
4
4
 
5
+ ## [1.1.22] - 2026-09-30
6
+
7
+ - 随 1.1.22 版本线发布;无面向用户的行为变化。
8
+
5
9
  ## [1.1.19] - 2026-09-22
6
10
 
7
11
  - 版本线推进;本版无独立用户可见变化。
@@ -78,8 +78,8 @@ below.
78
78
  uutils coreutils (https://github.com/uutils/coreutils), MIT
79
79
  --------------------------------------------------------------------------------
80
80
  Covers: base32, base64, basename, cat, cksum (shared checksum machinery),
81
- b2sum, md5sum, sha1sum, sha224sum, sha256sum, sha384sum, sha512sum, comm, cut,
82
- date, dirname, head, hostname, ln, ls, mkdir, mktemp, mv, nproc, paste,
81
+ b2sum, md5sum, sha1sum, sha224sum, sha256sum, sha384sum, sha512sum, comm, cp,
82
+ cut, date, dirname, head, hostname, ln, ls, mkdir, mktemp, mv, nproc, paste,
83
83
  printenv, readlink, realpath, rm, seq, sort, stat, tac, tail, tee, touch, tr,
84
84
  truncate, uname, uniq, wc, whoami, yes.
85
85
 
@@ -293,7 +293,7 @@ MIT License
293
293
  Copyright (c) 2026 Sander Land
294
294
  (measured tokenizer vocabulary data, reconstruction model, and reference
295
295
  implementation: https://github.com/sanderland/ctok)
296
- Copyright (c) 2026 Can Bölük and the Oh My Pi contributors
296
+ Copyright (c) 2026 Can Bölük and the omp contributors
297
297
  Copyright (c) 2026 Stencil Labs, Inc.
298
298
  (Rust implementation and the compact binary vocabulary encoding in
299
299
  crates/pi-natives/src/utok/claude)
@@ -335,43 +335,6 @@ This license allows the work and adaptations of it to be shared and used
335
335
  commercially, as long as it is attributed to Poppy Works. The font is bundled
336
336
  here (crates/pi-natives/src/fonts/Silver.ttf) as a CJK/Unicode bitmap fallback.
337
337
 
338
- -------------------------------------------------------------------------------
339
- packages/utils/src/vendor/mermaid-ascii/NOTICE
340
-
341
- This directory contains an in-house Mermaid-diagram-to-ASCII renderer adapted
342
- from beautiful-mermaid (https://github.com/lukilabs/beautiful-mermaid), used
343
- under the MIT License.
344
-
345
- Copyright (c) 2026 Craft Docs
346
-
347
- Only the ASCII rendering pipeline is ported (flowchart/state, sequence, class,
348
- ER, and xychart diagrams); the SVG renderer and its `elkjs` graph-layout
349
- dependency, the browser entry point, and the SVG theme/style modules were
350
- dropped. Terminal display width is reimplemented on `Bun.stringWidth`, and
351
- inline label formatting (HTML tags, markdown emphasis) is reduced to plain text
352
- for ASCII output. Layout and edge-routing logic is preserved faithfully so
353
- ASCII output matches the upstream package.
354
-
355
- MIT License
356
-
357
- Permission is hereby granted, free of charge, to any person obtaining a copy
358
- of this software and associated documentation files (the "Software"), to deal
359
- in the Software without restriction, including without limitation the rights
360
- to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
361
- copies of the Software, and to permit persons to whom the Software is
362
- furnished to do so, subject to the following conditions:
363
-
364
- The above copyright notice and this permission notice shall be included in all
365
- copies or substantial portions of the Software.
366
-
367
- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
368
- IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
369
- FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
370
- AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
371
- LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
372
- OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
373
- SOFTWARE.
374
-
375
338
  -------------------------------------------------------------------------------
376
339
  packages/coding-agent/src/markit/NOTICE
377
340
 
@@ -0,0 +1,293 @@
1
+ /**
2
+ * Wire contract for Skillshare (`skills.omp.sh`): an npm-style registry for
3
+ * omp skills. Shared by the omp CLI (`omp skill …`), the Go server
4
+ * (`stencil/apps/skills`), and its web UI (which mirrors this file).
5
+ *
6
+ * Packages are scoped: `@scope/name`. A scope is a Stencil username claimed on
7
+ * first publish and bound to the account's immutable `sub` forever (usernames
8
+ * can be renamed and recycled; scopes cannot). `name` is the SKILL.md
9
+ * frontmatter `name`. Published versions are immutable.
10
+ *
11
+ * Registry fields ride in SKILL.md `metadata` (the Agent Skills frontmatter is
12
+ * closed to name/description/license/compatibility/metadata/allowed-tools):
13
+ * `metadata.version` (semver, required to publish), `metadata.keywords`
14
+ * (comma-separated), `metadata.repository`, `metadata.homepage`.
15
+ */
16
+ /** Default registry; `skills.registryUrl` overrides it. */
17
+ export declare const DEFAULT_SKILLS_URL = "https://skills.omp.sh";
18
+ /** Scopes are Stencil usernames (or registry orgs): lowercase letters, digits, underscores; 3–32 chars. */
19
+ export declare const SKILL_SCOPE_RE: RegExp;
20
+ /** Registry skill names: ASCII kebab-case, 1–64 chars, no leading/trailing/double hyphens. */
21
+ export declare const SKILL_NAME_RE: RegExp;
22
+ export declare const SKILL_NAME_MAX = 64;
23
+ /** `@scope/name`, optionally `@version-or-range-or-tag`. */
24
+ export declare const SKILL_SPEC_RE: RegExp;
25
+ /** Publish limits, enforced by both the CLI and the server. */
26
+ export declare const SKILL_LIMITS: {
27
+ /** Compressed `.tgz` upload. */
28
+ readonly tarballBytes: number;
29
+ /** Sum of all file sizes after unpacking. */
30
+ readonly unpackedBytes: number;
31
+ readonly files: 1000;
32
+ /** Longest path inside the package. */
33
+ readonly pathLength: 255;
34
+ readonly descriptionLength: 1024;
35
+ readonly keywords: 20;
36
+ readonly keywordLength: 50;
37
+ readonly deprecationLength: 500;
38
+ };
39
+ /** Paths excluded from packs in addition to `.skillignore` entries. */
40
+ export declare const SKILL_DEFAULT_IGNORES: readonly [".git", ".DS_Store", "node_modules", "__pycache__", "*.pyc", "evals", ".skillignore"];
41
+ /**
42
+ * Publish request: `PUT SKILLS_ROUTES.publish(scope, name, version)`, body is
43
+ * the `.tgz` (gzip tar; entries are paths relative to the skill root, regular
44
+ * files only, sorted, mtime 0, mode 0644 or 0755). Auth: `Authorization:
45
+ * Bearer <Stencil access token | registry publish token>`.
46
+ */
47
+ export declare const SKILL_HEADERS: {
48
+ /** Required: SRI `sha512-<base64>` of the body. */
49
+ readonly integrity: "X-Skill-Integrity";
50
+ /** Optional dist-tag to point at the new version (default `latest` for stable, none for prereleases). */
51
+ readonly tag: "X-Skill-Tag";
52
+ /** Optional base64(JSON {@link SkillReportedProvenance}); shown as "reported". */
53
+ readonly provenance: "X-Skill-Provenance";
54
+ /** Optional GitHub Actions OIDC token (audience {@link SKILLS_OIDC_AUDIENCE}); verified server-side. */
55
+ readonly githubOidc: "X-Skill-GitHub-OIDC";
56
+ };
57
+ /** Audience CI must request for GitHub Actions OIDC tokens. */
58
+ export declare const SKILLS_OIDC_AUDIENCE = "skills.omp.sh";
59
+ /** Env var holding a registry publish token for CI (`sks_…`); wins over the Stencil login. */
60
+ export declare const SKILLS_TOKEN_ENV = "SKILLS_TOKEN";
61
+ /** Public identity of an account: current username + avatar seed (hash of the immutable sub). */
62
+ export interface SkillUser {
63
+ username: string;
64
+ /** Hex seed for the generated dither avatar; never the raw sub. */
65
+ avatar: string;
66
+ }
67
+ export interface SkillReportedProvenance {
68
+ ompVersion: string;
69
+ gitRemote?: string;
70
+ gitCommit?: string;
71
+ }
72
+ /** Provenance proven by a verified GitHub Actions OIDC token. */
73
+ export interface SkillVerifiedProvenance {
74
+ kind: "github-actions";
75
+ repository: string;
76
+ workflow: string;
77
+ ref: string;
78
+ sha: string;
79
+ runUrl: string;
80
+ }
81
+ export interface SkillProvenance {
82
+ publisher: SkillUser;
83
+ /** Publish came from a registry token rather than an interactive login. */
84
+ viaToken: boolean;
85
+ reported?: SkillReportedProvenance;
86
+ verified?: SkillVerifiedProvenance;
87
+ }
88
+ export interface SkillFile {
89
+ /** POSIX path relative to the skill root. */
90
+ path: string;
91
+ size: number;
92
+ /** Hex SHA-256 of the content. */
93
+ sha256: string;
94
+ executable: boolean;
95
+ }
96
+ /** One version as listed in a packument. */
97
+ export interface SkillVersionSummary {
98
+ version: string;
99
+ publishedAt: number;
100
+ publisher: SkillUser;
101
+ integrity: string;
102
+ size: number;
103
+ unpackedSize: number;
104
+ fileCount: number;
105
+ /** Ships executables or anything under `scripts/`. */
106
+ hasScripts: boolean;
107
+ yanked: boolean;
108
+ deprecated?: string;
109
+ }
110
+ /** Daily download counts, oldest first: `[YYYY-MM-DD, count]`. */
111
+ export type SkillDownloadSeries = [day: string, count: number][];
112
+ /** `GET SKILLS_ROUTES.packument`: everything about a package. */
113
+ export interface SkillPackument {
114
+ scope: string;
115
+ name: string;
116
+ /** From the `latest` version. */
117
+ description: string;
118
+ keywords: string[];
119
+ license?: string;
120
+ repository?: string;
121
+ homepage?: string;
122
+ owners: SkillUser[];
123
+ /** e.g. `{ latest: "1.2.0", next: "2.0.0-beta.1" }`. */
124
+ distTags: Record<string, string>;
125
+ versions: Record<string, SkillVersionSummary>;
126
+ createdAt: number;
127
+ updatedAt: number;
128
+ downloads: {
129
+ weekly: number;
130
+ total: number;
131
+ daily: SkillDownloadSeries;
132
+ };
133
+ /** Signed-in viewer may publish, tag, yank, deprecate, and manage owners. */
134
+ canManage: boolean;
135
+ }
136
+ /** `GET SKILLS_ROUTES.version`: one immutable version. `:version` may be a dist-tag. */
137
+ export interface SkillVersionManifest extends SkillVersionSummary {
138
+ scope: string;
139
+ name: string;
140
+ description: string;
141
+ license?: string;
142
+ compatibility?: string;
143
+ allowedTools?: string;
144
+ /** SKILL.md `metadata` verbatim. */
145
+ metadata: Record<string, string>;
146
+ keywords: string[];
147
+ repository?: string;
148
+ homepage?: string;
149
+ files: SkillFile[];
150
+ /** Package path rendered as the README (`README.md` if present, else `SKILL.md`). */
151
+ readmePath: string;
152
+ provenance: SkillProvenance;
153
+ }
154
+ /** `GET SKILLS_ROUTES.readme`: sanitized HTML rendered at publish time. */
155
+ export interface SkillReadme {
156
+ html: string;
157
+ }
158
+ /** `GET SKILLS_ROUTES.source`: one file for the code viewer. */
159
+ export interface SkillSource {
160
+ path: string;
161
+ size: number;
162
+ /** Binary or over the view limit: no `html`, offer `SKILLS_ROUTES.file` instead. */
163
+ binary: boolean;
164
+ tooLarge: boolean;
165
+ /** Server-highlighted, sanitized HTML: one `<span class="line">` per line. */
166
+ html?: string;
167
+ lines?: number;
168
+ }
169
+ export interface SkillSearchHit {
170
+ scope: string;
171
+ name: string;
172
+ description: string;
173
+ keywords: string[];
174
+ version: string;
175
+ publisher: SkillUser;
176
+ updatedAt: number;
177
+ weeklyDownloads: number;
178
+ deprecated?: string;
179
+ }
180
+ export type SkillSearchSort = "relevance" | "downloads" | "recent";
181
+ /** `GET SKILLS_ROUTES.search?q=&sort=&page=`. `q` accepts `owner:<scope>` and `keyword:<kw>` filters. */
182
+ export interface SkillSearchResponse {
183
+ total: number;
184
+ page: number;
185
+ perPage: number;
186
+ hits: SkillSearchHit[];
187
+ }
188
+ /** `GET SKILLS_ROUTES.home`. */
189
+ export interface SkillHome {
190
+ stats: {
191
+ packages: number;
192
+ versions: number;
193
+ publishers: number;
194
+ weeklyDownloads: number;
195
+ };
196
+ recent: SkillSearchHit[];
197
+ popular: SkillSearchHit[];
198
+ trending: SkillSearchHit[];
199
+ keywords: [keyword: string, count: number][];
200
+ }
201
+ /** `GET SKILLS_ROUTES.user`: a user or org scope page. */
202
+ export interface SkillProfile {
203
+ user: SkillUser;
204
+ kind: "user" | "org";
205
+ scopes: string[];
206
+ packages: SkillSearchHit[];
207
+ /** Orgs only. */
208
+ members?: {
209
+ user: SkillUser;
210
+ role: SkillOrgRole;
211
+ }[];
212
+ }
213
+ export type SkillOrgRole = "owner" | "member";
214
+ export interface SkillPublishResponse {
215
+ scope: string;
216
+ name: string;
217
+ version: string;
218
+ integrity: string;
219
+ /** Package page. */
220
+ url: string;
221
+ /** Dist-tags now pointing at this version. */
222
+ tags: string[];
223
+ }
224
+ /** Registry publish token (CI). The secret is shown once, at creation. */
225
+ export interface SkillToken {
226
+ id: string;
227
+ name: string;
228
+ /** `@scope/name` packages the token may publish; empty = all packages the creator manages. */
229
+ packages: string[];
230
+ createdAt: number;
231
+ expiresAt?: number;
232
+ lastUsedAt?: number;
233
+ }
234
+ export interface SkillTokenCreated extends SkillToken {
235
+ /** `sks_…`; never retrievable again. */
236
+ token: string;
237
+ }
238
+ /** `GET SKILLS_ROUTES.me`. */
239
+ export interface SkillSession {
240
+ user: SkillUser | null;
241
+ /** Sign-in is configured on this server. */
242
+ login: boolean;
243
+ admin: boolean;
244
+ }
245
+ /** Error body of every non-2xx JSON response. */
246
+ export interface SkillError {
247
+ error: string;
248
+ }
249
+ /**
250
+ * HTTP routes, relative to the registry base URL. Mutations with a JSON body
251
+ * use the documented request shapes:
252
+ * - `tag` PUT `{ version }`, DELETE to remove (never `latest`)
253
+ * - `yank` POST `{ yanked: boolean }`
254
+ * - `deprecate` POST `{ message: string | null }`
255
+ * - `owner` PUT / DELETE (no body)
256
+ * - `tokens` POST `{ name, packages?: string[], expiresInDays?: number }`
257
+ * - `report` POST `{ reason: string }`
258
+ * - `takedown` POST `{ reason: string }` (admins)
259
+ * - `orgs` POST `{ name }`; `orgMember` PUT `{ role }` / DELETE
260
+ * - `importSkill` POST body = Claude `.skill` zip (bearer) → {@link SkillPublishResponse}
261
+ */
262
+ export declare const SKILLS_ROUTES: {
263
+ readonly home: "/api/v1/home";
264
+ readonly search: "/api/v1/search";
265
+ readonly packument: (scope: string, name: string) => string;
266
+ readonly version: (scope: string, name: string, version: string) => string;
267
+ readonly readme: (scope: string, name: string, version: string) => string;
268
+ /** 302 to a signed R2 link; counts one download. */
269
+ readonly tarball: (scope: string, name: string, version: string) => string;
270
+ /** Raw file, same-origin: text as text/plain, sniffed raster images inline, everything else as an attachment. */
271
+ readonly file: (scope: string, name: string, version: string, path: string) => string;
272
+ readonly source: (scope: string, name: string, version: string, path: string) => string;
273
+ readonly publish: (scope: string, name: string, version: string) => string;
274
+ readonly tag: (scope: string, name: string, tag: string) => string;
275
+ readonly yank: (scope: string, name: string, version: string) => string;
276
+ readonly deprecate: (scope: string, name: string, version: string) => string;
277
+ readonly owner: (scope: string, name: string, username: string) => string;
278
+ readonly report: (scope: string, name: string) => string;
279
+ readonly takedown: (scope: string, name: string) => string;
280
+ readonly user: (username: string) => string;
281
+ readonly tokens: "/api/v1/tokens";
282
+ readonly token: (id: string) => string;
283
+ readonly orgs: "/api/v1/orgs";
284
+ readonly orgMember: (org: string, username: string) => string;
285
+ readonly importSkill: "/api/v1/import";
286
+ readonly me: "/api/me";
287
+ /** Web pages. */
288
+ readonly pages: {
289
+ readonly package: (scope: string, name: string) => string;
290
+ readonly user: (username: string) => string;
291
+ readonly search: (query: string) => string;
292
+ };
293
+ };
@@ -179,6 +179,18 @@ export declare const STREAM_CLOSE_FORBIDDEN = 4403;
179
179
  /** Provider id under which `/login` stores the stencil.so credential; `STENCIL_API_KEY` overrides it. */
180
180
  export declare const STREAM_AUTH_PROVIDER = "stencil";
181
181
  export declare const STREAM_AUTH_ENV = "STENCIL_API_KEY";
182
+ /** Longest accepted clip description (runes). Titles share `STREAM_TITLE_MAX`. */
183
+ export declare const CLIP_DESCRIPTION_MAX = 5000;
184
+ /**
185
+ * `POST /api/clips` answer. The body is an `.ompcast` recording (optionally
186
+ * `Content-Encoding: gzip`) whose header may carry `title` and `description`;
187
+ * the bearer identifies the uploading Stencil account.
188
+ */
189
+ export interface ClipUploadResponse {
190
+ id: string;
191
+ /** Public clip page, `<server>/c/<id>`. */
192
+ url: string;
193
+ }
182
194
  /** HTTP/WS route layout of the stream server, relative to `DEFAULT_STREAM_URL`. */
183
195
  export declare const STREAM_ROUTES: {
184
196
  readonly channels: "/api/channels";
@@ -187,4 +199,7 @@ export declare const STREAM_ROUTES: {
187
199
  readonly host: "/ws/host";
188
200
  readonly watch: (name: string) => string;
189
201
  readonly page: (name: string) => string;
202
+ /** Clip upload (bearer-authenticated `POST`). */
203
+ readonly clips: "/api/clips";
204
+ readonly clipPage: (id: string) => string;
190
205
  };
package/package.json CHANGED
@@ -1,8 +1,8 @@
1
1
  {
2
2
  "type": "module",
3
3
  "name": "@linxiraos/pi-wire",
4
- "version": "1.1.19",
5
- "description": "Shared wire protocol types for Oh My Pi packages",
4
+ "version": "1.1.22",
5
+ "description": "Shared wire protocol types for omp packages",
6
6
  "homepage": "https://linxira-os.github.io/zeta/",
7
7
  "author": "Can Boluk",
8
8
  "license": "MIT",
@@ -27,8 +27,7 @@
27
27
  "check:types": "tsgo -p tsconfig.json --noEmit",
28
28
  "lint": "oxlint .",
29
29
  "fix": "oxlint --fix --fix-suggestions . && bun run fmt",
30
- "fmt": "oxfmt --no-error-on-unmatched-pattern 'src/**/*.{ts,tsx}' '{test,bench,examples,scripts}/**/*.ts' '*.ts'",
31
- "test": "bun test --parallel"
30
+ "fmt": "oxfmt --no-error-on-unmatched-pattern 'src/**/*.{ts,tsx}' '{test,bench,examples,scripts}/**/*.ts' '*.ts'"
32
31
  },
33
32
  "devDependencies": {
34
33
  "@types/bun": "^1.3.14"
@@ -0,0 +1,323 @@
1
+ /**
2
+ * Wire contract for Skillshare (`skills.omp.sh`): an npm-style registry for
3
+ * omp skills. Shared by the omp CLI (`omp skill …`), the Go server
4
+ * (`stencil/apps/skills`), and its web UI (which mirrors this file).
5
+ *
6
+ * Packages are scoped: `@scope/name`. A scope is a Stencil username claimed on
7
+ * first publish and bound to the account's immutable `sub` forever (usernames
8
+ * can be renamed and recycled; scopes cannot). `name` is the SKILL.md
9
+ * frontmatter `name`. Published versions are immutable.
10
+ *
11
+ * Registry fields ride in SKILL.md `metadata` (the Agent Skills frontmatter is
12
+ * closed to name/description/license/compatibility/metadata/allowed-tools):
13
+ * `metadata.version` (semver, required to publish), `metadata.keywords`
14
+ * (comma-separated), `metadata.repository`, `metadata.homepage`.
15
+ */
16
+
17
+ /** Default registry; `skills.registryUrl` overrides it. */
18
+ export const DEFAULT_SKILLS_URL = "https://skills.omp.sh";
19
+
20
+ /** Scopes are Stencil usernames (or registry orgs): lowercase letters, digits, underscores; 3–32 chars. */
21
+ export const SKILL_SCOPE_RE = /^[a-z0-9][a-z0-9_]{2,31}$/;
22
+ /** Registry skill names: ASCII kebab-case, 1–64 chars, no leading/trailing/double hyphens. */
23
+ export const SKILL_NAME_RE = /^[a-z0-9]+(?:-[a-z0-9]+)*$/;
24
+ export const SKILL_NAME_MAX = 64;
25
+ /** `@scope/name`, optionally `@version-or-range-or-tag`. */
26
+ export const SKILL_SPEC_RE = /^@([a-z0-9][a-z0-9_]{2,31})\/([a-z0-9]+(?:-[a-z0-9]+)*)(?:@(.+))?$/;
27
+
28
+ /** Publish limits, enforced by both the CLI and the server. */
29
+ export const SKILL_LIMITS = {
30
+ /** Compressed `.tgz` upload. */
31
+ tarballBytes: 5 * 1024 * 1024,
32
+ /** Sum of all file sizes after unpacking. */
33
+ unpackedBytes: 20 * 1024 * 1024,
34
+ files: 1000,
35
+ /** Longest path inside the package. */
36
+ pathLength: 255,
37
+ descriptionLength: 1024,
38
+ keywords: 20,
39
+ keywordLength: 50,
40
+ deprecationLength: 500,
41
+ } as const;
42
+
43
+ /** Paths excluded from packs in addition to `.skillignore` entries. */
44
+ export const SKILL_DEFAULT_IGNORES = [
45
+ ".git",
46
+ ".DS_Store",
47
+ "node_modules",
48
+ "__pycache__",
49
+ "*.pyc",
50
+ "evals",
51
+ ".skillignore",
52
+ ] as const;
53
+
54
+ /**
55
+ * Publish request: `PUT SKILLS_ROUTES.publish(scope, name, version)`, body is
56
+ * the `.tgz` (gzip tar; entries are paths relative to the skill root, regular
57
+ * files only, sorted, mtime 0, mode 0644 or 0755). Auth: `Authorization:
58
+ * Bearer <Stencil access token | registry publish token>`.
59
+ */
60
+ export const SKILL_HEADERS = {
61
+ /** Required: SRI `sha512-<base64>` of the body. */
62
+ integrity: "X-Skill-Integrity",
63
+ /** Optional dist-tag to point at the new version (default `latest` for stable, none for prereleases). */
64
+ tag: "X-Skill-Tag",
65
+ /** Optional base64(JSON {@link SkillReportedProvenance}); shown as "reported". */
66
+ provenance: "X-Skill-Provenance",
67
+ /** Optional GitHub Actions OIDC token (audience {@link SKILLS_OIDC_AUDIENCE}); verified server-side. */
68
+ githubOidc: "X-Skill-GitHub-OIDC",
69
+ } as const;
70
+
71
+ /** Audience CI must request for GitHub Actions OIDC tokens. */
72
+ export const SKILLS_OIDC_AUDIENCE = "skills.omp.sh";
73
+
74
+ /** Env var holding a registry publish token for CI (`sks_…`); wins over the Stencil login. */
75
+ export const SKILLS_TOKEN_ENV = "SKILLS_TOKEN";
76
+
77
+ /** Public identity of an account: current username + avatar seed (hash of the immutable sub). */
78
+ export interface SkillUser {
79
+ username: string;
80
+ /** Hex seed for the generated dither avatar; never the raw sub. */
81
+ avatar: string;
82
+ }
83
+
84
+ export interface SkillReportedProvenance {
85
+ ompVersion: string;
86
+ gitRemote?: string;
87
+ gitCommit?: string;
88
+ }
89
+
90
+ /** Provenance proven by a verified GitHub Actions OIDC token. */
91
+ export interface SkillVerifiedProvenance {
92
+ kind: "github-actions";
93
+ repository: string;
94
+ workflow: string;
95
+ ref: string;
96
+ sha: string;
97
+ runUrl: string;
98
+ }
99
+
100
+ export interface SkillProvenance {
101
+ publisher: SkillUser;
102
+ /** Publish came from a registry token rather than an interactive login. */
103
+ viaToken: boolean;
104
+ reported?: SkillReportedProvenance;
105
+ verified?: SkillVerifiedProvenance;
106
+ }
107
+
108
+ export interface SkillFile {
109
+ /** POSIX path relative to the skill root. */
110
+ path: string;
111
+ size: number;
112
+ /** Hex SHA-256 of the content. */
113
+ sha256: string;
114
+ executable: boolean;
115
+ }
116
+
117
+ /** One version as listed in a packument. */
118
+ export interface SkillVersionSummary {
119
+ version: string;
120
+ publishedAt: number;
121
+ publisher: SkillUser;
122
+ integrity: string;
123
+ size: number;
124
+ unpackedSize: number;
125
+ fileCount: number;
126
+ /** Ships executables or anything under `scripts/`. */
127
+ hasScripts: boolean;
128
+ yanked: boolean;
129
+ deprecated?: string;
130
+ }
131
+
132
+ /** Daily download counts, oldest first: `[YYYY-MM-DD, count]`. */
133
+ export type SkillDownloadSeries = [day: string, count: number][];
134
+
135
+ /** `GET SKILLS_ROUTES.packument`: everything about a package. */
136
+ export interface SkillPackument {
137
+ scope: string;
138
+ name: string;
139
+ /** From the `latest` version. */
140
+ description: string;
141
+ keywords: string[];
142
+ license?: string;
143
+ repository?: string;
144
+ homepage?: string;
145
+ owners: SkillUser[];
146
+ /** e.g. `{ latest: "1.2.0", next: "2.0.0-beta.1" }`. */
147
+ distTags: Record<string, string>;
148
+ versions: Record<string, SkillVersionSummary>;
149
+ createdAt: number;
150
+ updatedAt: number;
151
+ downloads: { weekly: number; total: number; daily: SkillDownloadSeries };
152
+ /** Signed-in viewer may publish, tag, yank, deprecate, and manage owners. */
153
+ canManage: boolean;
154
+ }
155
+
156
+ /** `GET SKILLS_ROUTES.version`: one immutable version. `:version` may be a dist-tag. */
157
+ export interface SkillVersionManifest extends SkillVersionSummary {
158
+ scope: string;
159
+ name: string;
160
+ description: string;
161
+ license?: string;
162
+ compatibility?: string;
163
+ allowedTools?: string;
164
+ /** SKILL.md `metadata` verbatim. */
165
+ metadata: Record<string, string>;
166
+ keywords: string[];
167
+ repository?: string;
168
+ homepage?: string;
169
+ files: SkillFile[];
170
+ /** Package path rendered as the README (`README.md` if present, else `SKILL.md`). */
171
+ readmePath: string;
172
+ provenance: SkillProvenance;
173
+ }
174
+
175
+ /** `GET SKILLS_ROUTES.readme`: sanitized HTML rendered at publish time. */
176
+ export interface SkillReadme {
177
+ html: string;
178
+ }
179
+
180
+ /** `GET SKILLS_ROUTES.source`: one file for the code viewer. */
181
+ export interface SkillSource {
182
+ path: string;
183
+ size: number;
184
+ /** Binary or over the view limit: no `html`, offer `SKILLS_ROUTES.file` instead. */
185
+ binary: boolean;
186
+ tooLarge: boolean;
187
+ /** Server-highlighted, sanitized HTML: one `<span class="line">` per line. */
188
+ html?: string;
189
+ lines?: number;
190
+ }
191
+
192
+ export interface SkillSearchHit {
193
+ scope: string;
194
+ name: string;
195
+ description: string;
196
+ keywords: string[];
197
+ version: string;
198
+ publisher: SkillUser;
199
+ updatedAt: number;
200
+ weeklyDownloads: number;
201
+ deprecated?: string;
202
+ }
203
+
204
+ export type SkillSearchSort = "relevance" | "downloads" | "recent";
205
+
206
+ /** `GET SKILLS_ROUTES.search?q=&sort=&page=`. `q` accepts `owner:<scope>` and `keyword:<kw>` filters. */
207
+ export interface SkillSearchResponse {
208
+ total: number;
209
+ page: number;
210
+ perPage: number;
211
+ hits: SkillSearchHit[];
212
+ }
213
+
214
+ /** `GET SKILLS_ROUTES.home`. */
215
+ export interface SkillHome {
216
+ stats: { packages: number; versions: number; publishers: number; weeklyDownloads: number };
217
+ recent: SkillSearchHit[];
218
+ popular: SkillSearchHit[];
219
+ trending: SkillSearchHit[];
220
+ keywords: [keyword: string, count: number][];
221
+ }
222
+
223
+ /** `GET SKILLS_ROUTES.user`: a user or org scope page. */
224
+ export interface SkillProfile {
225
+ user: SkillUser;
226
+ kind: "user" | "org";
227
+ scopes: string[];
228
+ packages: SkillSearchHit[];
229
+ /** Orgs only. */
230
+ members?: { user: SkillUser; role: SkillOrgRole }[];
231
+ }
232
+
233
+ export type SkillOrgRole = "owner" | "member";
234
+
235
+ export interface SkillPublishResponse {
236
+ scope: string;
237
+ name: string;
238
+ version: string;
239
+ integrity: string;
240
+ /** Package page. */
241
+ url: string;
242
+ /** Dist-tags now pointing at this version. */
243
+ tags: string[];
244
+ }
245
+
246
+ /** Registry publish token (CI). The secret is shown once, at creation. */
247
+ export interface SkillToken {
248
+ id: string;
249
+ name: string;
250
+ /** `@scope/name` packages the token may publish; empty = all packages the creator manages. */
251
+ packages: string[];
252
+ createdAt: number;
253
+ expiresAt?: number;
254
+ lastUsedAt?: number;
255
+ }
256
+
257
+ export interface SkillTokenCreated extends SkillToken {
258
+ /** `sks_…`; never retrievable again. */
259
+ token: string;
260
+ }
261
+
262
+ /** `GET SKILLS_ROUTES.me`. */
263
+ export interface SkillSession {
264
+ user: SkillUser | null;
265
+ /** Sign-in is configured on this server. */
266
+ login: boolean;
267
+ admin: boolean;
268
+ }
269
+
270
+ /** Error body of every non-2xx JSON response. */
271
+ export interface SkillError {
272
+ error: string;
273
+ }
274
+
275
+ const pkg = (scope: string, name: string) => `/api/v1/skills/@${scope}/${name}`;
276
+
277
+ /**
278
+ * HTTP routes, relative to the registry base URL. Mutations with a JSON body
279
+ * use the documented request shapes:
280
+ * - `tag` PUT `{ version }`, DELETE to remove (never `latest`)
281
+ * - `yank` POST `{ yanked: boolean }`
282
+ * - `deprecate` POST `{ message: string | null }`
283
+ * - `owner` PUT / DELETE (no body)
284
+ * - `tokens` POST `{ name, packages?: string[], expiresInDays?: number }`
285
+ * - `report` POST `{ reason: string }`
286
+ * - `takedown` POST `{ reason: string }` (admins)
287
+ * - `orgs` POST `{ name }`; `orgMember` PUT `{ role }` / DELETE
288
+ * - `importSkill` POST body = Claude `.skill` zip (bearer) → {@link SkillPublishResponse}
289
+ */
290
+ export const SKILLS_ROUTES = {
291
+ home: "/api/v1/home",
292
+ search: "/api/v1/search",
293
+ packument: (scope: string, name: string) => pkg(scope, name),
294
+ version: (scope: string, name: string, version: string) => `${pkg(scope, name)}/versions/${version}`,
295
+ readme: (scope: string, name: string, version: string) => `${pkg(scope, name)}/versions/${version}/readme`,
296
+ /** 302 to a signed R2 link; counts one download. */
297
+ tarball: (scope: string, name: string, version: string) => `${pkg(scope, name)}/versions/${version}/tarball`,
298
+ /** Raw file, same-origin: text as text/plain, sniffed raster images inline, everything else as an attachment. */
299
+ file: (scope: string, name: string, version: string, path: string) =>
300
+ `${pkg(scope, name)}/versions/${version}/files/${path}`,
301
+ source: (scope: string, name: string, version: string, path: string) =>
302
+ `${pkg(scope, name)}/versions/${version}/source/${path}`,
303
+ publish: (scope: string, name: string, version: string) => `${pkg(scope, name)}/versions/${version}`,
304
+ tag: (scope: string, name: string, tag: string) => `${pkg(scope, name)}/tags/${tag}`,
305
+ yank: (scope: string, name: string, version: string) => `${pkg(scope, name)}/versions/${version}/yank`,
306
+ deprecate: (scope: string, name: string, version: string) => `${pkg(scope, name)}/versions/${version}/deprecate`,
307
+ owner: (scope: string, name: string, username: string) => `${pkg(scope, name)}/owners/${username}`,
308
+ report: (scope: string, name: string) => `${pkg(scope, name)}/report`,
309
+ takedown: (scope: string, name: string) => `/api/v1/admin/skills/@${scope}/${name}/takedown`,
310
+ user: (username: string) => `/api/v1/users/${username}`,
311
+ tokens: "/api/v1/tokens",
312
+ token: (id: string) => `/api/v1/tokens/${id}`,
313
+ orgs: "/api/v1/orgs",
314
+ orgMember: (org: string, username: string) => `/api/v1/orgs/${org}/members/${username}`,
315
+ importSkill: "/api/v1/import",
316
+ me: "/api/me",
317
+ /** Web pages. */
318
+ pages: {
319
+ package: (scope: string, name: string) => `/@${scope}/${name}`,
320
+ user: (username: string) => `/~${username}`,
321
+ search: (query: string) => `/search?q=${encodeURIComponent(query)}`,
322
+ },
323
+ } as const;
package/src/stream.ts CHANGED
@@ -141,6 +141,20 @@ export const STREAM_CLOSE_FORBIDDEN = 4403;
141
141
  export const STREAM_AUTH_PROVIDER = "stencil";
142
142
  export const STREAM_AUTH_ENV = "STENCIL_API_KEY";
143
143
 
144
+ /** Longest accepted clip description (runes). Titles share `STREAM_TITLE_MAX`. */
145
+ export const CLIP_DESCRIPTION_MAX = 5000;
146
+
147
+ /**
148
+ * `POST /api/clips` answer. The body is an `.ompcast` recording (optionally
149
+ * `Content-Encoding: gzip`) whose header may carry `title` and `description`;
150
+ * the bearer identifies the uploading Stencil account.
151
+ */
152
+ export interface ClipUploadResponse {
153
+ id: string;
154
+ /** Public clip page, `<server>/c/<id>`. */
155
+ url: string;
156
+ }
157
+
144
158
  /** HTTP/WS route layout of the stream server, relative to `DEFAULT_STREAM_URL`. */
145
159
  export const STREAM_ROUTES = {
146
160
  channels: "/api/channels",
@@ -149,4 +163,7 @@ export const STREAM_ROUTES = {
149
163
  host: "/ws/host",
150
164
  watch: (name: string) => `/ws/watch/${name}`,
151
165
  page: (name: string) => `/${name}`,
166
+ /** Clip upload (bearer-authenticated `POST`). */
167
+ clips: "/api/clips",
168
+ clipPage: (id: string) => `/c/${id}`,
152
169
  } as const;