@hasna/skills 0.5.2 → 0.5.4
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/README.md +169 -1
- package/bin/index.js +1541 -1042
- package/bin/mcp.js +28461 -27173
- package/bin/migrate.js +9 -1
- package/bin/server.js +80 -56
- package/bin/worker.js +80 -56
- package/dist/admin-contract.js +168 -166
- package/dist/cli/commands/invitation-recovery.d.ts +2 -0
- package/dist/cli/commands/invitation-verification.d.ts +8 -0
- package/dist/cli/commands/workspace-invitations.d.ts +2 -0
- package/dist/index.d.ts +6 -2
- package/dist/index.js +1516 -611
- package/dist/lib/invitation-customer-action.d.ts +14 -0
- package/dist/lib/invitation-recovery-target.d.ts +5 -0
- package/dist/lib/remote-auth.d.ts +12 -0
- package/dist/lib/remote-client.d.ts +19 -0
- package/dist/lib/remote-invitation-recovery.d.ts +62 -0
- package/dist/lib/remote-invitations.d.ts +128 -0
- package/dist/lib/remote-quote-errors.d.ts +12 -0
- package/dist/lib/skill-bundle.d.ts +54 -1
- package/dist/lib/skill-entry-path.d.ts +6 -0
- package/dist/lib/skill-hash.d.ts +33 -0
- package/dist/mcp/index.d.ts +0 -1
- package/dist/mcp/invitation-recovery.d.ts +2 -0
- package/dist/mcp/remote-invitation-tools.d.ts +2 -0
- package/dist/sdk/index.d.ts +5 -1
- package/dist/sdk/index.js +1316 -389
- package/dist/sdk/registry.d.ts +6 -0
- package/dist/storage.js +35 -33
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -19,12 +19,14 @@ var __toESM = (mod, isNodeMode, target) => {
|
|
|
19
19
|
}
|
|
20
20
|
target = mod != null ? __create(__getProtoOf(mod)) : {};
|
|
21
21
|
const to = isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target;
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
22
|
+
if (mod && typeof mod === "object" || typeof mod === "function") {
|
|
23
|
+
for (let key of __getOwnPropNames(mod))
|
|
24
|
+
if (!__hasOwnProp.call(to, key))
|
|
25
|
+
__defProp(to, key, {
|
|
26
|
+
get: __accessProp.bind(mod, key),
|
|
27
|
+
enumerable: true
|
|
28
|
+
});
|
|
29
|
+
}
|
|
28
30
|
if (canCache)
|
|
29
31
|
cache.set(mod, to);
|
|
30
32
|
return to;
|
|
@@ -1463,8 +1465,45 @@ function validateRegistryConsistency(registry, skillsDir) {
|
|
|
1463
1465
|
import { createHash } from "crypto";
|
|
1464
1466
|
import { existsSync as existsSync5, readdirSync as readdirSync4, readFileSync as readFileSync4, statSync as statSync4 } from "fs";
|
|
1465
1467
|
import { join as join5, sep } from "path";
|
|
1468
|
+
|
|
1469
|
+
// src/lib/skill-entry-path.ts
|
|
1470
|
+
class SkillEntryPaths {
|
|
1471
|
+
files = new Set;
|
|
1472
|
+
directories = new Set;
|
|
1473
|
+
add(path, maxBytes, invalid, limit) {
|
|
1474
|
+
if (path.length > maxBytes)
|
|
1475
|
+
limit();
|
|
1476
|
+
const encoded = new TextEncoder().encode(path);
|
|
1477
|
+
if (encoded.byteLength > maxBytes)
|
|
1478
|
+
limit();
|
|
1479
|
+
if (new TextDecoder("utf-8", { fatal: true, ignoreBOM: true }).decode(encoded) !== path)
|
|
1480
|
+
invalid("Invalid UTF-8 entry path");
|
|
1481
|
+
if (!path || /[\\:\x00-\x1f\x7f]/u.test(path))
|
|
1482
|
+
invalid("Unsafe entry path");
|
|
1483
|
+
if (path.split("/").some((segment) => !segment || segment === "." || segment === ".."))
|
|
1484
|
+
invalid("Unsafe entry path segment");
|
|
1485
|
+
const key = path.normalize("NFC").toLowerCase().normalize("NFC");
|
|
1486
|
+
if (this.files.has(key) || this.directories.has(key))
|
|
1487
|
+
invalid("Duplicate or conflicting entry path");
|
|
1488
|
+
const parents = key.split("/");
|
|
1489
|
+
parents.pop();
|
|
1490
|
+
while (parents.length) {
|
|
1491
|
+
const parent = parents.join("/");
|
|
1492
|
+
if (this.files.has(parent))
|
|
1493
|
+
invalid("Conflicting entry file ancestor");
|
|
1494
|
+
this.directories.add(parent);
|
|
1495
|
+
parents.pop();
|
|
1496
|
+
}
|
|
1497
|
+
this.files.add(key);
|
|
1498
|
+
}
|
|
1499
|
+
}
|
|
1500
|
+
|
|
1501
|
+
// src/lib/skill-hash.ts
|
|
1466
1502
|
var CONTENT_HASH_ALGORITHM = "sha256";
|
|
1467
1503
|
var HASH_EXCLUDE_DIRS = new Set([".git", "node_modules", "dist", "build", ".turbo"]);
|
|
1504
|
+
function excludedHashEntry(name, directory) {
|
|
1505
|
+
return name.startsWith(".") || directory && HASH_EXCLUDE_DIRS.has(name);
|
|
1506
|
+
}
|
|
1468
1507
|
var HASH_COVERAGE = [
|
|
1469
1508
|
"SKILL.md",
|
|
1470
1509
|
"skill.json",
|
|
@@ -1546,7 +1585,7 @@ function collectDirectory(files, dir, rel) {
|
|
|
1546
1585
|
if (stats.isSymbolicLink())
|
|
1547
1586
|
continue;
|
|
1548
1587
|
if (stats.isDirectory()) {
|
|
1549
|
-
if (
|
|
1588
|
+
if (excludedHashEntry(entry, true))
|
|
1550
1589
|
continue;
|
|
1551
1590
|
collectDirectory(files, absolute, childRel);
|
|
1552
1591
|
} else if (stats.isFile()) {
|
|
@@ -1556,28 +1595,242 @@ function collectDirectory(files, dir, rel) {
|
|
|
1556
1595
|
}
|
|
1557
1596
|
function collectFile(files, absolute, rel) {
|
|
1558
1597
|
const buffer = readFileSync4(absolute);
|
|
1598
|
+
files.push(normalizeBundleFile(rel.split(sep).join("/"), buffer));
|
|
1599
|
+
}
|
|
1600
|
+
function normalizeBundleFile(rel, buffer) {
|
|
1559
1601
|
if (rel === "skill.json") {
|
|
1560
|
-
|
|
1561
|
-
return;
|
|
1602
|
+
return { rel, content: new TextEncoder().encode(canonicalizeManifest(new TextDecoder().decode(buffer))) };
|
|
1562
1603
|
}
|
|
1563
1604
|
if (looksLikeText(buffer)) {
|
|
1564
1605
|
const normalized = normalizeLineEndings(new TextDecoder().decode(buffer));
|
|
1565
|
-
|
|
1566
|
-
return;
|
|
1606
|
+
return { rel, content: new TextEncoder().encode(normalized) };
|
|
1567
1607
|
}
|
|
1568
|
-
|
|
1608
|
+
return { rel, content: buffer };
|
|
1569
1609
|
}
|
|
1570
1610
|
function computeContentHash(skillPath) {
|
|
1611
|
+
return hashBundleFiles(collectBundleFiles(skillPath));
|
|
1612
|
+
}
|
|
1613
|
+
function* bundleHashParts(files) {
|
|
1614
|
+
for (const file of files) {
|
|
1615
|
+
yield new TextEncoder().encode(file.rel);
|
|
1616
|
+
yield new TextEncoder().encode(`\x00${file.content.length}\x00`);
|
|
1617
|
+
yield file.content;
|
|
1618
|
+
yield new TextEncoder().encode("\x00");
|
|
1619
|
+
}
|
|
1620
|
+
yield new TextEncoder().encode("\x00");
|
|
1621
|
+
}
|
|
1622
|
+
function hashBundleFiles(files) {
|
|
1623
|
+
const hash = createHash(CONTENT_HASH_ALGORITHM);
|
|
1624
|
+
for (const part of bundleHashParts(files))
|
|
1625
|
+
hash.update(part);
|
|
1626
|
+
return hash.digest("hex");
|
|
1627
|
+
}
|
|
1628
|
+
async function hashBundleFilesCooperatively(files, check) {
|
|
1571
1629
|
const hash = createHash(CONTENT_HASH_ALGORITHM);
|
|
1572
|
-
|
|
1573
|
-
|
|
1574
|
-
|
|
1575
|
-
|
|
1576
|
-
|
|
1630
|
+
let bytesSinceYield = 0;
|
|
1631
|
+
for (const part of bundleHashParts(files)) {
|
|
1632
|
+
for (let offset = 0;offset < part.byteLength; offset += 64 * 1024) {
|
|
1633
|
+
check();
|
|
1634
|
+
const chunk = part.subarray(offset, offset + 64 * 1024);
|
|
1635
|
+
hash.update(chunk);
|
|
1636
|
+
bytesSinceYield += chunk.byteLength;
|
|
1637
|
+
if (bytesSinceYield >= 256 * 1024) {
|
|
1638
|
+
await new Promise((resolve2) => setImmediate(resolve2));
|
|
1639
|
+
bytesSinceYield = 0;
|
|
1640
|
+
}
|
|
1641
|
+
}
|
|
1577
1642
|
}
|
|
1578
|
-
|
|
1643
|
+
check();
|
|
1579
1644
|
return hash.digest("hex");
|
|
1580
1645
|
}
|
|
1646
|
+
var CONTENT_HASH_LIMITS = Object.freeze({
|
|
1647
|
+
entries: 1024,
|
|
1648
|
+
rawBytes: 64 * 1024 * 1024,
|
|
1649
|
+
normalizedBytes: 64 * 1024 * 1024,
|
|
1650
|
+
fileBytes: 16 * 1024 * 1024,
|
|
1651
|
+
normalizedFileBytes: 16 * 1024 * 1024,
|
|
1652
|
+
pathBytes: 100,
|
|
1653
|
+
manifestBytes: 16 * 1024,
|
|
1654
|
+
manifestDepth: 64,
|
|
1655
|
+
timeoutMs: 5000
|
|
1656
|
+
});
|
|
1657
|
+
|
|
1658
|
+
class ContentHashInputError extends Error {
|
|
1659
|
+
code;
|
|
1660
|
+
constructor(code, message) {
|
|
1661
|
+
super(message);
|
|
1662
|
+
this.code = code;
|
|
1663
|
+
this.name = "ContentHashInputError";
|
|
1664
|
+
}
|
|
1665
|
+
}
|
|
1666
|
+
function invalidContent(message = "Invalid content hash input") {
|
|
1667
|
+
throw new ContentHashInputError("CONTENT_HASH_INVALID", message);
|
|
1668
|
+
}
|
|
1669
|
+
function contentLimit(message) {
|
|
1670
|
+
throw new ContentHashInputError("CONTENT_HASH_LIMIT", message);
|
|
1671
|
+
}
|
|
1672
|
+
function contentRecord(value, allowed) {
|
|
1673
|
+
if (!value || typeof value !== "object" || ![Object.prototype, null].includes(Object.getPrototypeOf(value)))
|
|
1674
|
+
invalidContent();
|
|
1675
|
+
const result = Object.create(null);
|
|
1676
|
+
for (const key of Reflect.ownKeys(value)) {
|
|
1677
|
+
if (typeof key !== "string" || !allowed.includes(key))
|
|
1678
|
+
invalidContent();
|
|
1679
|
+
const descriptor = Object.getOwnPropertyDescriptor(value, key);
|
|
1680
|
+
if (!descriptor || !("value" in descriptor))
|
|
1681
|
+
invalidContent("Accessor content hash input is unsupported");
|
|
1682
|
+
result[key] = descriptor.value;
|
|
1683
|
+
}
|
|
1684
|
+
return result;
|
|
1685
|
+
}
|
|
1686
|
+
function contentOptions(options) {
|
|
1687
|
+
const record = contentRecord(options, ["limits", "signal"]);
|
|
1688
|
+
const limits = { ...CONTENT_HASH_LIMITS };
|
|
1689
|
+
if (record.limits !== undefined) {
|
|
1690
|
+
const supplied = contentRecord(record.limits, Object.keys(limits));
|
|
1691
|
+
for (const key of Object.keys(supplied)) {
|
|
1692
|
+
const value = supplied[key];
|
|
1693
|
+
if (typeof value !== "number" || !Number.isSafeInteger(value) || value <= 0 || value > limits[key])
|
|
1694
|
+
contentLimit("Invalid content hash limit");
|
|
1695
|
+
limits[key] = value;
|
|
1696
|
+
}
|
|
1697
|
+
}
|
|
1698
|
+
if (record.signal !== undefined && !(record.signal instanceof AbortSignal))
|
|
1699
|
+
invalidContent("Invalid content hash signal");
|
|
1700
|
+
return { limits, signal: record.signal };
|
|
1701
|
+
}
|
|
1702
|
+
var typedArrayPrototype = Object.getPrototypeOf(Uint8Array.prototype);
|
|
1703
|
+
var byteLengthOf = Object.getOwnPropertyDescriptor(typedArrayPrototype, "byteLength").get;
|
|
1704
|
+
var bufferOf = Object.getOwnPropertyDescriptor(typedArrayPrototype, "buffer").get;
|
|
1705
|
+
function snapshotContentEntries(entries, limits, check) {
|
|
1706
|
+
if (!Array.isArray(entries))
|
|
1707
|
+
invalidContent("Content hash entries must be an array");
|
|
1708
|
+
if (entries.length > limits.entries)
|
|
1709
|
+
contentLimit("Content hash entry limit exceeded");
|
|
1710
|
+
if (Reflect.ownKeys(entries).length !== entries.length + 1)
|
|
1711
|
+
invalidContent("Invalid content hash entry array");
|
|
1712
|
+
const snapshot = [];
|
|
1713
|
+
const paths = new SkillEntryPaths;
|
|
1714
|
+
let rawBytes = 0;
|
|
1715
|
+
for (let index = 0;index < entries.length; index++) {
|
|
1716
|
+
check();
|
|
1717
|
+
const descriptor = Object.getOwnPropertyDescriptor(entries, String(index));
|
|
1718
|
+
if (!descriptor || !("value" in descriptor))
|
|
1719
|
+
invalidContent("Invalid content hash entry array");
|
|
1720
|
+
const entry = contentRecord(descriptor.value, ["path", "bytes", "mode"]);
|
|
1721
|
+
if (typeof entry.path !== "string" || typeof entry.mode !== "number" || !Number.isInteger(entry.mode) || entry.mode < 0 || entry.mode > 511)
|
|
1722
|
+
invalidContent("Invalid regular-file content hash entry");
|
|
1723
|
+
paths.add(entry.path, limits.pathBytes, invalidContent, () => contentLimit("Content hash path limit exceeded"));
|
|
1724
|
+
if (!(entry.bytes instanceof Uint8Array) || !ArrayBuffer.isView(entry.bytes))
|
|
1725
|
+
invalidContent("Content hash entry requires bytes");
|
|
1726
|
+
const size = byteLengthOf.call(entry.bytes);
|
|
1727
|
+
if (!(bufferOf.call(entry.bytes) instanceof ArrayBuffer))
|
|
1728
|
+
invalidContent("Shared content hash bytes are unsupported");
|
|
1729
|
+
if (size > limits.fileBytes || rawBytes + size > limits.rawBytes)
|
|
1730
|
+
contentLimit("Content hash raw byte limit exceeded");
|
|
1731
|
+
if (entry.path === "skill.json" && size > limits.manifestBytes)
|
|
1732
|
+
contentLimit("Content hash manifest byte limit exceeded");
|
|
1733
|
+
rawBytes += size;
|
|
1734
|
+
const bytes = new Uint8Array(new ArrayBuffer(size));
|
|
1735
|
+
bytes.set(entry.bytes);
|
|
1736
|
+
snapshot.push({ path: entry.path, bytes, mode: entry.mode });
|
|
1737
|
+
}
|
|
1738
|
+
check();
|
|
1739
|
+
return snapshot;
|
|
1740
|
+
}
|
|
1741
|
+
function coveredContentPath(path) {
|
|
1742
|
+
const segments = path.split("/");
|
|
1743
|
+
if (!HASH_COVERAGE.includes(segments[0]))
|
|
1744
|
+
return false;
|
|
1745
|
+
return !segments.slice(1).some((segment, index) => excludedHashEntry(segment, index < segments.length - 2));
|
|
1746
|
+
}
|
|
1747
|
+
function boundedManifest(raw, maxDepth) {
|
|
1748
|
+
let parsed;
|
|
1749
|
+
try {
|
|
1750
|
+
parsed = JSON.parse(raw);
|
|
1751
|
+
} catch {
|
|
1752
|
+
return;
|
|
1753
|
+
}
|
|
1754
|
+
const pending = [{ value: parsed, depth: 1 }];
|
|
1755
|
+
while (pending.length) {
|
|
1756
|
+
const { value, depth } = pending.pop();
|
|
1757
|
+
if (!value || typeof value !== "object")
|
|
1758
|
+
continue;
|
|
1759
|
+
if (depth > maxDepth)
|
|
1760
|
+
contentLimit("Content hash manifest depth limit exceeded");
|
|
1761
|
+
for (const child of Object.values(value))
|
|
1762
|
+
pending.push({ value: child, depth: depth + 1 });
|
|
1763
|
+
}
|
|
1764
|
+
return parsed;
|
|
1765
|
+
}
|
|
1766
|
+
async function hashContentEntries(entries, options) {
|
|
1767
|
+
const { limits, signal } = contentOptions(options);
|
|
1768
|
+
const deadline = performance.now() + limits.timeoutMs;
|
|
1769
|
+
let terminal;
|
|
1770
|
+
const abort = () => {
|
|
1771
|
+
terminal ??= new ContentHashInputError("CONTENT_HASH_ABORTED", "Content hashing aborted");
|
|
1772
|
+
};
|
|
1773
|
+
const timer = setTimeout(() => {
|
|
1774
|
+
terminal ??= new ContentHashInputError("CONTENT_HASH_TIMEOUT", "Content hashing deadline exceeded");
|
|
1775
|
+
}, limits.timeoutMs);
|
|
1776
|
+
const check = () => {
|
|
1777
|
+
if (signal?.aborted)
|
|
1778
|
+
abort();
|
|
1779
|
+
if (terminal)
|
|
1780
|
+
throw terminal;
|
|
1781
|
+
if (performance.now() >= deadline)
|
|
1782
|
+
throw new ContentHashInputError("CONTENT_HASH_TIMEOUT", "Content hashing deadline exceeded");
|
|
1783
|
+
};
|
|
1784
|
+
try {
|
|
1785
|
+
signal?.addEventListener("abort", abort, { once: true });
|
|
1786
|
+
check();
|
|
1787
|
+
const snapshot = snapshotContentEntries(entries, limits, check);
|
|
1788
|
+
const normalized = [];
|
|
1789
|
+
let normalizedBytes = 0;
|
|
1790
|
+
let manifest;
|
|
1791
|
+
await new Promise((resolve2) => setImmediate(resolve2));
|
|
1792
|
+
for (const entry of snapshot) {
|
|
1793
|
+
check();
|
|
1794
|
+
if (!coveredContentPath(entry.path))
|
|
1795
|
+
continue;
|
|
1796
|
+
if (entry.path === "skill.json")
|
|
1797
|
+
manifest = boundedManifest(new TextDecoder().decode(entry.bytes), limits.manifestDepth);
|
|
1798
|
+
const file = normalizeBundleFile(entry.path, entry.bytes);
|
|
1799
|
+
check();
|
|
1800
|
+
if (file.content.byteLength > limits.normalizedFileBytes || normalizedBytes + file.content.byteLength > limits.normalizedBytes)
|
|
1801
|
+
contentLimit("Content hash normalized byte limit exceeded");
|
|
1802
|
+
normalizedBytes += file.content.byteLength;
|
|
1803
|
+
normalized.push(file);
|
|
1804
|
+
await new Promise((resolve2) => setImmediate(resolve2));
|
|
1805
|
+
}
|
|
1806
|
+
normalized.sort((a, b) => a.rel < b.rel ? -1 : a.rel > b.rel ? 1 : 0);
|
|
1807
|
+
check();
|
|
1808
|
+
return { hash: await hashBundleFilesCooperatively(normalized, check), manifest };
|
|
1809
|
+
} catch (error) {
|
|
1810
|
+
if (error instanceof ContentHashInputError)
|
|
1811
|
+
throw error;
|
|
1812
|
+
throw new ContentHashInputError("CONTENT_HASH_INVALID", "Invalid content hash input");
|
|
1813
|
+
} finally {
|
|
1814
|
+
clearTimeout(timer);
|
|
1815
|
+
signal?.removeEventListener("abort", abort);
|
|
1816
|
+
}
|
|
1817
|
+
}
|
|
1818
|
+
async function computeContentHashFromEntries(entries, options = {}) {
|
|
1819
|
+
return (await hashContentEntries(entries, options)).hash;
|
|
1820
|
+
}
|
|
1821
|
+
async function verifyContentHashFromEntries(entries, options = {}) {
|
|
1822
|
+
const { hash, manifest } = await hashContentEntries(entries, options);
|
|
1823
|
+
const provenance = manifest && typeof manifest === "object" && !Array.isArray(manifest) ? manifest.provenance : undefined;
|
|
1824
|
+
const value = provenance && typeof provenance === "object" && !Array.isArray(provenance) ? provenance.content_hash : undefined;
|
|
1825
|
+
if (value !== undefined && typeof value !== "string")
|
|
1826
|
+
invalidContent("Invalid content hash declaration");
|
|
1827
|
+
const declaredHash = value?.trim() || undefined;
|
|
1828
|
+
if (!declaredHash)
|
|
1829
|
+
return { declared: false, valid: false };
|
|
1830
|
+
if (!/^[a-f0-9]{64}$/.test(declaredHash))
|
|
1831
|
+
return { declared: true, valid: false, declaredHash };
|
|
1832
|
+
return { declared: true, valid: hash === declaredHash, declaredHash, computedHash: hash };
|
|
1833
|
+
}
|
|
1581
1834
|
function verifyContentHash(skillPath, manifest) {
|
|
1582
1835
|
const declaredHash = manifest?.provenance?.content_hash?.trim() || undefined;
|
|
1583
1836
|
if (!declaredHash)
|
|
@@ -4478,207 +4731,207 @@ function readIfExists(path) {
|
|
|
4478
4731
|
// ../../node_modules/.bun/zod@3.25.76/node_modules/zod/v3/external.js
|
|
4479
4732
|
var exports_external = {};
|
|
4480
4733
|
__export(exports_external, {
|
|
4481
|
-
|
|
4482
|
-
util: () => util,
|
|
4483
|
-
unknown: () => unknownType,
|
|
4484
|
-
union: () => unionType,
|
|
4485
|
-
undefined: () => undefinedType,
|
|
4486
|
-
tuple: () => tupleType,
|
|
4487
|
-
transformer: () => effectsType,
|
|
4488
|
-
symbol: () => symbolType,
|
|
4489
|
-
string: () => stringType,
|
|
4490
|
-
strictObject: () => strictObjectType,
|
|
4491
|
-
setErrorMap: () => setErrorMap,
|
|
4492
|
-
set: () => setType,
|
|
4493
|
-
record: () => recordType,
|
|
4494
|
-
quotelessJson: () => quotelessJson,
|
|
4495
|
-
promise: () => promiseType,
|
|
4496
|
-
preprocess: () => preprocessType,
|
|
4497
|
-
pipeline: () => pipelineType,
|
|
4498
|
-
ostring: () => ostring,
|
|
4499
|
-
optional: () => optionalType,
|
|
4500
|
-
onumber: () => onumber,
|
|
4501
|
-
oboolean: () => oboolean,
|
|
4502
|
-
objectUtil: () => objectUtil,
|
|
4503
|
-
object: () => objectType,
|
|
4504
|
-
number: () => numberType,
|
|
4505
|
-
nullable: () => nullableType,
|
|
4506
|
-
null: () => nullType,
|
|
4507
|
-
never: () => neverType,
|
|
4508
|
-
nativeEnum: () => nativeEnumType,
|
|
4509
|
-
nan: () => nanType,
|
|
4510
|
-
map: () => mapType,
|
|
4511
|
-
makeIssue: () => makeIssue,
|
|
4512
|
-
literal: () => literalType,
|
|
4513
|
-
lazy: () => lazyType,
|
|
4514
|
-
late: () => late,
|
|
4515
|
-
isValid: () => isValid,
|
|
4516
|
-
isDirty: () => isDirty,
|
|
4517
|
-
isAsync: () => isAsync,
|
|
4518
|
-
isAborted: () => isAborted,
|
|
4519
|
-
intersection: () => intersectionType,
|
|
4520
|
-
instanceof: () => instanceOfType,
|
|
4521
|
-
getParsedType: () => getParsedType,
|
|
4522
|
-
getErrorMap: () => getErrorMap,
|
|
4523
|
-
function: () => functionType,
|
|
4524
|
-
enum: () => enumType,
|
|
4525
|
-
effect: () => effectsType,
|
|
4526
|
-
discriminatedUnion: () => discriminatedUnionType,
|
|
4527
|
-
defaultErrorMap: () => en_default,
|
|
4528
|
-
datetimeRegex: () => datetimeRegex,
|
|
4529
|
-
date: () => dateType,
|
|
4530
|
-
custom: () => custom,
|
|
4531
|
-
coerce: () => coerce,
|
|
4532
|
-
boolean: () => booleanType,
|
|
4533
|
-
bigint: () => bigIntType,
|
|
4534
|
-
array: () => arrayType,
|
|
4535
|
-
any: () => anyType,
|
|
4536
|
-
addIssueToContext: () => addIssueToContext,
|
|
4537
|
-
ZodVoid: () => ZodVoid,
|
|
4538
|
-
ZodUnknown: () => ZodUnknown,
|
|
4539
|
-
ZodUnion: () => ZodUnion,
|
|
4540
|
-
ZodUndefined: () => ZodUndefined,
|
|
4541
|
-
ZodType: () => ZodType,
|
|
4542
|
-
ZodTuple: () => ZodTuple,
|
|
4543
|
-
ZodTransformer: () => ZodEffects,
|
|
4544
|
-
ZodSymbol: () => ZodSymbol,
|
|
4545
|
-
ZodString: () => ZodString,
|
|
4546
|
-
ZodSet: () => ZodSet,
|
|
4547
|
-
ZodSchema: () => ZodType,
|
|
4548
|
-
ZodRecord: () => ZodRecord,
|
|
4549
|
-
ZodReadonly: () => ZodReadonly,
|
|
4550
|
-
ZodPromise: () => ZodPromise,
|
|
4551
|
-
ZodPipeline: () => ZodPipeline,
|
|
4552
|
-
ZodParsedType: () => ZodParsedType,
|
|
4553
|
-
ZodOptional: () => ZodOptional,
|
|
4554
|
-
ZodObject: () => ZodObject,
|
|
4555
|
-
ZodNumber: () => ZodNumber,
|
|
4556
|
-
ZodNullable: () => ZodNullable,
|
|
4557
|
-
ZodNull: () => ZodNull,
|
|
4558
|
-
ZodNever: () => ZodNever,
|
|
4559
|
-
ZodNativeEnum: () => ZodNativeEnum,
|
|
4560
|
-
ZodNaN: () => ZodNaN,
|
|
4561
|
-
ZodMap: () => ZodMap,
|
|
4562
|
-
ZodLiteral: () => ZodLiteral,
|
|
4563
|
-
ZodLazy: () => ZodLazy,
|
|
4564
|
-
ZodIssueCode: () => ZodIssueCode,
|
|
4565
|
-
ZodIntersection: () => ZodIntersection,
|
|
4566
|
-
ZodFunction: () => ZodFunction,
|
|
4567
|
-
ZodFirstPartyTypeKind: () => ZodFirstPartyTypeKind,
|
|
4568
|
-
ZodError: () => ZodError,
|
|
4569
|
-
ZodEnum: () => ZodEnum,
|
|
4570
|
-
ZodEffects: () => ZodEffects,
|
|
4571
|
-
ZodDiscriminatedUnion: () => ZodDiscriminatedUnion,
|
|
4572
|
-
ZodDefault: () => ZodDefault,
|
|
4573
|
-
ZodDate: () => ZodDate,
|
|
4574
|
-
ZodCatch: () => ZodCatch,
|
|
4575
|
-
ZodBranded: () => ZodBranded,
|
|
4576
|
-
ZodBoolean: () => ZodBoolean,
|
|
4577
|
-
ZodBigInt: () => ZodBigInt,
|
|
4578
|
-
ZodArray: () => ZodArray,
|
|
4579
|
-
ZodAny: () => ZodAny,
|
|
4580
|
-
Schema: () => ZodType,
|
|
4581
|
-
ParseStatus: () => ParseStatus,
|
|
4582
|
-
OK: () => OK,
|
|
4583
|
-
NEVER: () => NEVER,
|
|
4584
|
-
INVALID: () => INVALID,
|
|
4585
|
-
EMPTY_PATH: () => EMPTY_PATH,
|
|
4734
|
+
BRAND: () => BRAND,
|
|
4586
4735
|
DIRTY: () => DIRTY,
|
|
4587
|
-
|
|
4588
|
-
|
|
4589
|
-
|
|
4590
|
-
|
|
4591
|
-
|
|
4592
|
-
(
|
|
4593
|
-
|
|
4594
|
-
|
|
4595
|
-
|
|
4596
|
-
|
|
4597
|
-
|
|
4598
|
-
|
|
4599
|
-
|
|
4600
|
-
|
|
4601
|
-
|
|
4602
|
-
|
|
4603
|
-
|
|
4604
|
-
|
|
4605
|
-
|
|
4606
|
-
|
|
4607
|
-
|
|
4608
|
-
|
|
4609
|
-
|
|
4610
|
-
|
|
4611
|
-
|
|
4612
|
-
|
|
4613
|
-
|
|
4614
|
-
|
|
4615
|
-
|
|
4616
|
-
|
|
4617
|
-
|
|
4618
|
-
|
|
4619
|
-
|
|
4620
|
-
|
|
4621
|
-
|
|
4622
|
-
|
|
4623
|
-
|
|
4624
|
-
|
|
4625
|
-
|
|
4626
|
-
|
|
4627
|
-
|
|
4628
|
-
|
|
4629
|
-
|
|
4630
|
-
|
|
4631
|
-
|
|
4632
|
-
|
|
4633
|
-
|
|
4634
|
-
|
|
4635
|
-
|
|
4636
|
-
|
|
4637
|
-
|
|
4638
|
-
|
|
4639
|
-
|
|
4640
|
-
|
|
4641
|
-
|
|
4642
|
-
|
|
4643
|
-
|
|
4644
|
-
|
|
4645
|
-
|
|
4646
|
-
|
|
4647
|
-
|
|
4648
|
-
|
|
4649
|
-
|
|
4650
|
-
|
|
4651
|
-
|
|
4652
|
-
|
|
4653
|
-
|
|
4654
|
-
|
|
4655
|
-
|
|
4656
|
-
|
|
4657
|
-
|
|
4658
|
-
|
|
4659
|
-
|
|
4660
|
-
|
|
4661
|
-
|
|
4662
|
-
|
|
4663
|
-
|
|
4664
|
-
|
|
4665
|
-
|
|
4666
|
-
|
|
4667
|
-
|
|
4668
|
-
|
|
4669
|
-
|
|
4670
|
-
|
|
4671
|
-
|
|
4672
|
-
|
|
4673
|
-
|
|
4674
|
-
|
|
4675
|
-
|
|
4676
|
-
|
|
4677
|
-
|
|
4678
|
-
|
|
4679
|
-
|
|
4680
|
-
|
|
4681
|
-
|
|
4736
|
+
EMPTY_PATH: () => EMPTY_PATH,
|
|
4737
|
+
INVALID: () => INVALID,
|
|
4738
|
+
NEVER: () => NEVER,
|
|
4739
|
+
OK: () => OK,
|
|
4740
|
+
ParseStatus: () => ParseStatus,
|
|
4741
|
+
Schema: () => ZodType,
|
|
4742
|
+
ZodAny: () => ZodAny,
|
|
4743
|
+
ZodArray: () => ZodArray,
|
|
4744
|
+
ZodBigInt: () => ZodBigInt,
|
|
4745
|
+
ZodBoolean: () => ZodBoolean,
|
|
4746
|
+
ZodBranded: () => ZodBranded,
|
|
4747
|
+
ZodCatch: () => ZodCatch,
|
|
4748
|
+
ZodDate: () => ZodDate,
|
|
4749
|
+
ZodDefault: () => ZodDefault,
|
|
4750
|
+
ZodDiscriminatedUnion: () => ZodDiscriminatedUnion,
|
|
4751
|
+
ZodEffects: () => ZodEffects,
|
|
4752
|
+
ZodEnum: () => ZodEnum,
|
|
4753
|
+
ZodError: () => ZodError,
|
|
4754
|
+
ZodFirstPartyTypeKind: () => ZodFirstPartyTypeKind,
|
|
4755
|
+
ZodFunction: () => ZodFunction,
|
|
4756
|
+
ZodIntersection: () => ZodIntersection,
|
|
4757
|
+
ZodIssueCode: () => ZodIssueCode,
|
|
4758
|
+
ZodLazy: () => ZodLazy,
|
|
4759
|
+
ZodLiteral: () => ZodLiteral,
|
|
4760
|
+
ZodMap: () => ZodMap,
|
|
4761
|
+
ZodNaN: () => ZodNaN,
|
|
4762
|
+
ZodNativeEnum: () => ZodNativeEnum,
|
|
4763
|
+
ZodNever: () => ZodNever,
|
|
4764
|
+
ZodNull: () => ZodNull,
|
|
4765
|
+
ZodNullable: () => ZodNullable,
|
|
4766
|
+
ZodNumber: () => ZodNumber,
|
|
4767
|
+
ZodObject: () => ZodObject,
|
|
4768
|
+
ZodOptional: () => ZodOptional,
|
|
4769
|
+
ZodParsedType: () => ZodParsedType,
|
|
4770
|
+
ZodPipeline: () => ZodPipeline,
|
|
4771
|
+
ZodPromise: () => ZodPromise,
|
|
4772
|
+
ZodReadonly: () => ZodReadonly,
|
|
4773
|
+
ZodRecord: () => ZodRecord,
|
|
4774
|
+
ZodSchema: () => ZodType,
|
|
4775
|
+
ZodSet: () => ZodSet,
|
|
4776
|
+
ZodString: () => ZodString,
|
|
4777
|
+
ZodSymbol: () => ZodSymbol,
|
|
4778
|
+
ZodTransformer: () => ZodEffects,
|
|
4779
|
+
ZodTuple: () => ZodTuple,
|
|
4780
|
+
ZodType: () => ZodType,
|
|
4781
|
+
ZodUndefined: () => ZodUndefined,
|
|
4782
|
+
ZodUnion: () => ZodUnion,
|
|
4783
|
+
ZodUnknown: () => ZodUnknown,
|
|
4784
|
+
ZodVoid: () => ZodVoid,
|
|
4785
|
+
addIssueToContext: () => addIssueToContext,
|
|
4786
|
+
any: () => anyType,
|
|
4787
|
+
array: () => arrayType,
|
|
4788
|
+
bigint: () => bigIntType,
|
|
4789
|
+
boolean: () => booleanType,
|
|
4790
|
+
coerce: () => coerce,
|
|
4791
|
+
custom: () => custom,
|
|
4792
|
+
date: () => dateType,
|
|
4793
|
+
datetimeRegex: () => datetimeRegex,
|
|
4794
|
+
defaultErrorMap: () => en_default,
|
|
4795
|
+
discriminatedUnion: () => discriminatedUnionType,
|
|
4796
|
+
effect: () => effectsType,
|
|
4797
|
+
enum: () => enumType,
|
|
4798
|
+
function: () => functionType,
|
|
4799
|
+
getErrorMap: () => getErrorMap,
|
|
4800
|
+
getParsedType: () => getParsedType,
|
|
4801
|
+
instanceof: () => instanceOfType,
|
|
4802
|
+
intersection: () => intersectionType,
|
|
4803
|
+
isAborted: () => isAborted,
|
|
4804
|
+
isAsync: () => isAsync,
|
|
4805
|
+
isDirty: () => isDirty,
|
|
4806
|
+
isValid: () => isValid,
|
|
4807
|
+
late: () => late,
|
|
4808
|
+
lazy: () => lazyType,
|
|
4809
|
+
literal: () => literalType,
|
|
4810
|
+
makeIssue: () => makeIssue,
|
|
4811
|
+
map: () => mapType,
|
|
4812
|
+
nan: () => nanType,
|
|
4813
|
+
nativeEnum: () => nativeEnumType,
|
|
4814
|
+
never: () => neverType,
|
|
4815
|
+
null: () => nullType,
|
|
4816
|
+
nullable: () => nullableType,
|
|
4817
|
+
number: () => numberType,
|
|
4818
|
+
object: () => objectType,
|
|
4819
|
+
objectUtil: () => objectUtil,
|
|
4820
|
+
oboolean: () => oboolean,
|
|
4821
|
+
onumber: () => onumber,
|
|
4822
|
+
optional: () => optionalType,
|
|
4823
|
+
ostring: () => ostring,
|
|
4824
|
+
pipeline: () => pipelineType,
|
|
4825
|
+
preprocess: () => preprocessType,
|
|
4826
|
+
promise: () => promiseType,
|
|
4827
|
+
quotelessJson: () => quotelessJson,
|
|
4828
|
+
record: () => recordType,
|
|
4829
|
+
set: () => setType,
|
|
4830
|
+
setErrorMap: () => setErrorMap,
|
|
4831
|
+
strictObject: () => strictObjectType,
|
|
4832
|
+
string: () => stringType,
|
|
4833
|
+
symbol: () => symbolType,
|
|
4834
|
+
transformer: () => effectsType,
|
|
4835
|
+
tuple: () => tupleType,
|
|
4836
|
+
undefined: () => undefinedType,
|
|
4837
|
+
union: () => unionType,
|
|
4838
|
+
unknown: () => unknownType,
|
|
4839
|
+
util: () => util,
|
|
4840
|
+
void: () => voidType
|
|
4841
|
+
});
|
|
4842
|
+
|
|
4843
|
+
// ../../node_modules/.bun/zod@3.25.76/node_modules/zod/v3/helpers/util.js
|
|
4844
|
+
var util;
|
|
4845
|
+
(function(util2) {
|
|
4846
|
+
util2.assertEqual = (_) => {};
|
|
4847
|
+
function assertIs(_arg) {}
|
|
4848
|
+
util2.assertIs = assertIs;
|
|
4849
|
+
function assertNever(_x) {
|
|
4850
|
+
throw new Error;
|
|
4851
|
+
}
|
|
4852
|
+
util2.assertNever = assertNever;
|
|
4853
|
+
util2.arrayToEnum = (items) => {
|
|
4854
|
+
const obj = {};
|
|
4855
|
+
for (const item of items) {
|
|
4856
|
+
obj[item] = item;
|
|
4857
|
+
}
|
|
4858
|
+
return obj;
|
|
4859
|
+
};
|
|
4860
|
+
util2.getValidEnumValues = (obj) => {
|
|
4861
|
+
const validKeys2 = util2.objectKeys(obj).filter((k) => typeof obj[obj[k]] !== "number");
|
|
4862
|
+
const filtered = {};
|
|
4863
|
+
for (const k of validKeys2) {
|
|
4864
|
+
filtered[k] = obj[k];
|
|
4865
|
+
}
|
|
4866
|
+
return util2.objectValues(filtered);
|
|
4867
|
+
};
|
|
4868
|
+
util2.objectValues = (obj) => {
|
|
4869
|
+
return util2.objectKeys(obj).map(function(e) {
|
|
4870
|
+
return obj[e];
|
|
4871
|
+
});
|
|
4872
|
+
};
|
|
4873
|
+
util2.objectKeys = typeof Object.keys === "function" ? (obj) => Object.keys(obj) : (object) => {
|
|
4874
|
+
const keys = [];
|
|
4875
|
+
for (const key in object) {
|
|
4876
|
+
if (Object.prototype.hasOwnProperty.call(object, key)) {
|
|
4877
|
+
keys.push(key);
|
|
4878
|
+
}
|
|
4879
|
+
}
|
|
4880
|
+
return keys;
|
|
4881
|
+
};
|
|
4882
|
+
util2.find = (arr, checker) => {
|
|
4883
|
+
for (const item of arr) {
|
|
4884
|
+
if (checker(item))
|
|
4885
|
+
return item;
|
|
4886
|
+
}
|
|
4887
|
+
return;
|
|
4888
|
+
};
|
|
4889
|
+
util2.isInteger = typeof Number.isInteger === "function" ? (val) => Number.isInteger(val) : (val) => typeof val === "number" && Number.isFinite(val) && Math.floor(val) === val;
|
|
4890
|
+
function joinValues(array, separator = " | ") {
|
|
4891
|
+
return array.map((val) => typeof val === "string" ? `'${val}'` : val).join(separator);
|
|
4892
|
+
}
|
|
4893
|
+
util2.joinValues = joinValues;
|
|
4894
|
+
util2.jsonStringifyReplacer = (_, value) => {
|
|
4895
|
+
if (typeof value === "bigint") {
|
|
4896
|
+
return value.toString();
|
|
4897
|
+
}
|
|
4898
|
+
return value;
|
|
4899
|
+
};
|
|
4900
|
+
})(util || (util = {}));
|
|
4901
|
+
var objectUtil;
|
|
4902
|
+
(function(objectUtil2) {
|
|
4903
|
+
objectUtil2.mergeShapes = (first, second) => {
|
|
4904
|
+
return {
|
|
4905
|
+
...first,
|
|
4906
|
+
...second
|
|
4907
|
+
};
|
|
4908
|
+
};
|
|
4909
|
+
})(objectUtil || (objectUtil = {}));
|
|
4910
|
+
var ZodParsedType = util.arrayToEnum([
|
|
4911
|
+
"string",
|
|
4912
|
+
"nan",
|
|
4913
|
+
"number",
|
|
4914
|
+
"integer",
|
|
4915
|
+
"float",
|
|
4916
|
+
"boolean",
|
|
4917
|
+
"date",
|
|
4918
|
+
"bigint",
|
|
4919
|
+
"symbol",
|
|
4920
|
+
"function",
|
|
4921
|
+
"undefined",
|
|
4922
|
+
"null",
|
|
4923
|
+
"array",
|
|
4924
|
+
"object",
|
|
4925
|
+
"unknown",
|
|
4926
|
+
"promise",
|
|
4927
|
+
"void",
|
|
4928
|
+
"never",
|
|
4929
|
+
"map",
|
|
4930
|
+
"set"
|
|
4931
|
+
]);
|
|
4932
|
+
var getParsedType = (data) => {
|
|
4933
|
+
const t = typeof data;
|
|
4934
|
+
switch (t) {
|
|
4682
4935
|
case "undefined":
|
|
4683
4936
|
return ZodParsedType.undefined;
|
|
4684
4937
|
case "string":
|
|
@@ -10254,11 +10507,174 @@ function primitiveHaystack(primitive) {
|
|
|
10254
10507
|
function clone(value) {
|
|
10255
10508
|
return value === undefined ? undefined : JSON.parse(JSON.stringify(value));
|
|
10256
10509
|
}
|
|
10257
|
-
// src/lib/remote-
|
|
10510
|
+
// src/lib/remote-invitations.ts
|
|
10511
|
+
class WorkspaceInvitationInputError extends Error {
|
|
10512
|
+
code = "INVITATION_INPUT_INVALID";
|
|
10513
|
+
constructor() {
|
|
10514
|
+
super("Provide only the documented invitation fields, exact lowercase IDs, expected generation and explicit confirmation. Issue and resend require your stable idempotency key.");
|
|
10515
|
+
this.name = "WorkspaceInvitationInputError";
|
|
10516
|
+
}
|
|
10517
|
+
}
|
|
10518
|
+
var invitationFailures = {
|
|
10519
|
+
INVALID_REQUEST: [400, "Invitation parameters were refused."],
|
|
10520
|
+
ACCOUNT_UNAVAILABLE: [403, "Account is unavailable."],
|
|
10521
|
+
INTERACTIVE_SESSION_REQUIRED: [403, "Fresh interactive sign-in is required."],
|
|
10522
|
+
WORKSPACE_ADMIN_REQUIRED: [403, "A current workspace owner or admin is required."],
|
|
10523
|
+
INVITATION_FORBIDDEN: [403, "Your current role cannot manage this invitation."],
|
|
10524
|
+
INVITATION_UNAVAILABLE: [404, "Invitation is unavailable for this account."],
|
|
10525
|
+
INVITATION_CHANGED: [409, "Invitation changed. Read its current generation before another action."],
|
|
10526
|
+
INVITATION_EXISTS: [409, "A pending invitation already exists. Read current invitations."],
|
|
10527
|
+
ALREADY_MEMBER: [409, "An active membership already exists. An invitation cannot change its role."],
|
|
10528
|
+
IDEMPOTENCY_CONFLICT: [409, "This request key was used for different invitation parameters. Reconcile the original request."],
|
|
10529
|
+
INVITATION_LIMIT: [429, "Invitation limit reached. Wait before issuing or resending."],
|
|
10530
|
+
INVITATION_BUSY: [503, "Invitation is busy. Read its state before another action."],
|
|
10531
|
+
INVITATION_DELIVERY_UNAVAILABLE: [503, "Invitation email delivery is unavailable."]
|
|
10532
|
+
};
|
|
10533
|
+
|
|
10534
|
+
class RemoteWorkspaceInvitationError extends Error {
|
|
10535
|
+
code;
|
|
10536
|
+
status;
|
|
10537
|
+
constructor(code) {
|
|
10538
|
+
super(invitationFailures[code][1]);
|
|
10539
|
+
this.code = code;
|
|
10540
|
+
this.name = "RemoteWorkspaceInvitationError";
|
|
10541
|
+
this.status = invitationFailures[code][0];
|
|
10542
|
+
}
|
|
10543
|
+
}
|
|
10544
|
+
|
|
10545
|
+
class RemoteWorkspaceInvitationUnconfirmedError extends Error {
|
|
10546
|
+
code = "INVITATION_UNCONFIRMED";
|
|
10547
|
+
constructor() {
|
|
10548
|
+
super("The invitation outcome is unconfirmed. Read current invitations or memberships. Reconcile issue/resend only with the same request key, parameters, server and membership; never generate a new key or retry automatically. Saved credentials are unchanged.");
|
|
10549
|
+
this.name = "RemoteWorkspaceInvitationUnconfirmedError";
|
|
10550
|
+
}
|
|
10551
|
+
}
|
|
10552
|
+
|
|
10553
|
+
class RemoteWorkspaceInvitationReadError extends Error {
|
|
10554
|
+
code = "INVITATION_READ_FAILED";
|
|
10555
|
+
constructor() {
|
|
10556
|
+
super("Unable to read a valid invitation result. Check the selected server, account, current membership and permissions.");
|
|
10557
|
+
this.name = "RemoteWorkspaceInvitationReadError";
|
|
10558
|
+
}
|
|
10559
|
+
}
|
|
10560
|
+
function invitationFailure(value, status) {
|
|
10561
|
+
if (!record(value) || typeof value.code !== "string" || !Object.hasOwn(invitationFailures, value.code))
|
|
10562
|
+
return null;
|
|
10563
|
+
const code = value.code;
|
|
10564
|
+
return invitationFailures[code][0] === status ? code : null;
|
|
10565
|
+
}
|
|
10258
10566
|
var record = (v) => !!v && typeof v === "object" && !Array.isArray(v);
|
|
10259
10567
|
var uuid = (v) => typeof v === "string" && /^[a-f0-9]{8}-[a-f0-9]{4}-[a-f0-9]{4}-[a-f0-9]{4}-[a-f0-9]{12}$/.test(v);
|
|
10260
|
-
var text = (v, max = 1024) => typeof v === "string" && !!v.trim() && v.length <= max && !/[\p{Cc}\p{Cs}\u2028\u2029]/u.test(v);
|
|
10261
10568
|
var role = (v) => typeof v === "string" && ["owner", "admin", "member", "viewer"].includes(v);
|
|
10569
|
+
var email = (v) => typeof v === "string" && v.length <= 254 && !/[\p{Cc}\p{Cs}\u2028\u2029\s]/u.test(v) && /^[^@]+@[^@]+\.[^@]+$/.test(v);
|
|
10570
|
+
var timestamp = (v) => typeof v === "string" && v.length <= 40 && /^\d{4}-\d\d-\d\dT\d\d:\d\d:\d\d(?:\.\d{1,6})?(?:Z|[+-]\d\d:\d\d)$/.test(v) && Number.isFinite(Date.parse(v));
|
|
10571
|
+
var inputFailure = () => {
|
|
10572
|
+
throw new WorkspaceInvitationInputError;
|
|
10573
|
+
};
|
|
10574
|
+
function invitationInput(action, input) {
|
|
10575
|
+
if (!record(input))
|
|
10576
|
+
return inputFailure();
|
|
10577
|
+
const keys = {
|
|
10578
|
+
list: ["after"],
|
|
10579
|
+
get: ["invitationId"],
|
|
10580
|
+
issue: ["email", "role", "idempotencyKey", "confirm"],
|
|
10581
|
+
resend: ["invitationId", "expectedGeneration", "idempotencyKey", "confirm"],
|
|
10582
|
+
revoke: ["invitationId", "expectedGeneration", "confirm"],
|
|
10583
|
+
accept: ["invitationId", "token", "confirm"]
|
|
10584
|
+
};
|
|
10585
|
+
if (Object.keys(input).some((key) => !keys[action].includes(key)) || action !== "list" && keys[action].some((key) => !Object.hasOwn(input, key)))
|
|
10586
|
+
return inputFailure();
|
|
10587
|
+
const value = { ...input };
|
|
10588
|
+
if (action === "list") {
|
|
10589
|
+
if (value.after !== undefined && !uuid(value.after))
|
|
10590
|
+
return inputFailure();
|
|
10591
|
+
}
|
|
10592
|
+
if (["get", "resend", "revoke", "accept"].includes(action) && !uuid(value.invitationId))
|
|
10593
|
+
return inputFailure();
|
|
10594
|
+
if (!["list", "get"].includes(action) && value.confirm !== true)
|
|
10595
|
+
return inputFailure();
|
|
10596
|
+
if (["issue", "resend"].includes(action) && !uuid(value.idempotencyKey))
|
|
10597
|
+
return inputFailure();
|
|
10598
|
+
if (action === "issue") {
|
|
10599
|
+
if (typeof value.email !== "string")
|
|
10600
|
+
return inputFailure();
|
|
10601
|
+
value.email = value.email.trim().toLowerCase();
|
|
10602
|
+
if (!email(value.email) || !role(value.role))
|
|
10603
|
+
return inputFailure();
|
|
10604
|
+
}
|
|
10605
|
+
if (["resend", "revoke"].includes(action) && (!Number.isInteger(value.expectedGeneration) || Number(value.expectedGeneration) < 1 || Number(value.expectedGeneration) > 10))
|
|
10606
|
+
return inputFailure();
|
|
10607
|
+
if (action === "accept" && (typeof value.token !== "string" || !/^[A-Za-z0-9_-]{43}$/.test(value.token)))
|
|
10608
|
+
return inputFailure();
|
|
10609
|
+
return value;
|
|
10610
|
+
}
|
|
10611
|
+
function invitationRequest(action, input) {
|
|
10612
|
+
const base = "/api/v1/workspace/invitations", value = input;
|
|
10613
|
+
const { confirm: _confirm, invitationId: id, ...body } = value;
|
|
10614
|
+
if (action === "list")
|
|
10615
|
+
return { path: base + (value.after ? `?after=${value.after}` : ""), method: "GET" };
|
|
10616
|
+
if (action === "get")
|
|
10617
|
+
return { path: `${base}/${id}`, method: "GET" };
|
|
10618
|
+
if (action === "accept")
|
|
10619
|
+
return { path: "/api/v1/account/invitations/accept", method: "POST", body: JSON.stringify({ invitationId: id, token: value.token }) };
|
|
10620
|
+
return { path: action === "issue" ? base : `${base}/${id}${action === "resend" ? "/resend" : ""}`, method: action === "revoke" ? "DELETE" : "POST", body: JSON.stringify(body) };
|
|
10621
|
+
}
|
|
10622
|
+
function invalid() {
|
|
10623
|
+
throw new RemoteWorkspaceInvitationReadError;
|
|
10624
|
+
}
|
|
10625
|
+
function projection(v, organizationId) {
|
|
10626
|
+
if (!record(v) || !uuid(v.id) || v.organizationId !== organizationId || !email(v.email) || v.email !== v.email.trim().toLowerCase() || !role(v.role) || !Number.isInteger(v.generation) || Number(v.generation) < 1 || Number(v.generation) > 10 || typeof v.status !== "string" || !["pending", "expired", "accepted", "revoked"].includes(v.status) || !timestamp(v.expiresAt) || !timestamp(v.createdAt) || !record(v.delivery) || typeof v.delivery.state !== "string" || !["queued", "sending", "uncertain", "provider_accepted", "failed", "cancelled"].includes(v.delivery.state) || !Number.isInteger(v.delivery.attempts) || Number(v.delivery.attempts) < 0 || Number(v.delivery.attempts) > 5)
|
|
10627
|
+
return invalid();
|
|
10628
|
+
return {
|
|
10629
|
+
id: v.id,
|
|
10630
|
+
organizationId,
|
|
10631
|
+
email: v.email,
|
|
10632
|
+
role: v.role,
|
|
10633
|
+
generation: Number(v.generation),
|
|
10634
|
+
status: v.status,
|
|
10635
|
+
expiresAt: v.expiresAt,
|
|
10636
|
+
createdAt: v.createdAt,
|
|
10637
|
+
delivery: { state: v.delivery.state, attempts: Number(v.delivery.attempts) }
|
|
10638
|
+
};
|
|
10639
|
+
}
|
|
10640
|
+
function parseInvitationResult(action, value, input, organizationId) {
|
|
10641
|
+
if (!record(value))
|
|
10642
|
+
return invalid();
|
|
10643
|
+
const request = input;
|
|
10644
|
+
if (action === "accept") {
|
|
10645
|
+
if (!uuid(value.organizationId) || !uuid(value.membershipId) || value.accepted !== true || typeof value.changed !== "boolean")
|
|
10646
|
+
return invalid();
|
|
10647
|
+
return { organizationId: value.organizationId, membershipId: value.membershipId, accepted: true, changed: value.changed };
|
|
10648
|
+
}
|
|
10649
|
+
if (action === "list") {
|
|
10650
|
+
if (value.organizationId !== organizationId || !Array.isArray(value.invitations) || value.invitations.length > 50 || value.nextCursor !== null && !uuid(value.nextCursor))
|
|
10651
|
+
return invalid();
|
|
10652
|
+
const invitations = value.invitations.map((v) => projection(v, organizationId));
|
|
10653
|
+
if (invitations.some((v, n) => v.id <= String(n ? invitations[n - 1].id : request.after ?? "")) || value.nextCursor !== null && (invitations.length !== 50 || value.nextCursor !== invitations.at(-1)?.id))
|
|
10654
|
+
return invalid();
|
|
10655
|
+
return { organizationId, invitations, nextCursor: value.nextCursor };
|
|
10656
|
+
}
|
|
10657
|
+
const invitation = projection(value.invitation, organizationId);
|
|
10658
|
+
if (action !== "issue" && invitation.id !== request.invitationId)
|
|
10659
|
+
return invalid();
|
|
10660
|
+
if (action === "get")
|
|
10661
|
+
return { invitation };
|
|
10662
|
+
if (typeof value.changed !== "boolean")
|
|
10663
|
+
return invalid();
|
|
10664
|
+
if (action === "issue" && (invitation.email !== request.email || invitation.role !== request.role || value.changed && invitation.generation !== 1))
|
|
10665
|
+
return invalid();
|
|
10666
|
+
if (action === "resend" && (value.changed ? invitation.generation !== Number(request.expectedGeneration) + 1 : invitation.generation <= Number(request.expectedGeneration)))
|
|
10667
|
+
return invalid();
|
|
10668
|
+
if (action === "revoke" && (invitation.status !== "revoked" || invitation.generation < Number(request.expectedGeneration) || value.changed && invitation.generation !== request.expectedGeneration))
|
|
10669
|
+
return invalid();
|
|
10670
|
+
return { invitation, changed: value.changed };
|
|
10671
|
+
}
|
|
10672
|
+
|
|
10673
|
+
// src/lib/remote-workspace-selection.ts
|
|
10674
|
+
var record2 = (v) => !!v && typeof v === "object" && !Array.isArray(v);
|
|
10675
|
+
var uuid2 = (v) => typeof v === "string" && /^[a-f0-9]{8}-[a-f0-9]{4}-[a-f0-9]{4}-[a-f0-9]{4}-[a-f0-9]{12}$/.test(v);
|
|
10676
|
+
var text = (v, max = 1024) => typeof v === "string" && !!v.trim() && v.length <= max && !/[\p{Cc}\p{Cs}\u2028\u2029]/u.test(v);
|
|
10677
|
+
var role2 = (v) => typeof v === "string" && ["owner", "admin", "member", "viewer"].includes(v);
|
|
10262
10678
|
var invalidWorkspaceResult = "The server returned an invalid workspace selection result.";
|
|
10263
10679
|
|
|
10264
10680
|
class WorkspaceContextInputError extends Error {
|
|
@@ -10275,48 +10691,48 @@ class WorkspaceIdentityMismatchError extends Error {
|
|
|
10275
10691
|
}
|
|
10276
10692
|
}
|
|
10277
10693
|
function workspaceExpectedUserId(value) {
|
|
10278
|
-
if (!
|
|
10694
|
+
if (!uuid2(value))
|
|
10279
10695
|
throw new WorkspaceContextInputError;
|
|
10280
10696
|
return value;
|
|
10281
10697
|
}
|
|
10282
10698
|
function workspaceContext(value) {
|
|
10283
|
-
if (!
|
|
10699
|
+
if (!record2(value) || Object.keys(value).sort().join(",") !== "membershipId,userId" || !uuid2(value.userId) || !uuid2(value.membershipId))
|
|
10284
10700
|
throw new WorkspaceContextInputError;
|
|
10285
10701
|
return { userId: value.userId, membershipId: value.membershipId };
|
|
10286
10702
|
}
|
|
10287
|
-
function
|
|
10703
|
+
function invalid2() {
|
|
10288
10704
|
throw new Error(invalidWorkspaceResult);
|
|
10289
10705
|
}
|
|
10290
10706
|
function organization(v) {
|
|
10291
|
-
if (!
|
|
10292
|
-
return
|
|
10707
|
+
if (!record2(v) || !uuid2(v.id) || !text(v.slug) || !text(v.name))
|
|
10708
|
+
return invalid2();
|
|
10293
10709
|
return { id: v.id, slug: v.slug, name: v.name };
|
|
10294
10710
|
}
|
|
10295
10711
|
function parseAccountWorkspaces(value) {
|
|
10296
|
-
if (!
|
|
10297
|
-
return
|
|
10712
|
+
if (!record2(value) || !Array.isArray(value.workspaces) || !value.workspaces.length || value.workspaces.length > 1000)
|
|
10713
|
+
return invalid2();
|
|
10298
10714
|
const workspaces = value.workspaces.map((v) => {
|
|
10299
|
-
if (!
|
|
10300
|
-
return
|
|
10715
|
+
if (!record2(v) || !uuid2(v.membershipId) || !role2(v.role) || typeof v.current !== "boolean")
|
|
10716
|
+
return invalid2();
|
|
10301
10717
|
return { membershipId: v.membershipId, organization: organization(v.organization), role: v.role, current: v.current };
|
|
10302
10718
|
});
|
|
10303
10719
|
if (workspaces.filter((w) => w.current).length !== 1 || new Set(workspaces.map((w) => w.membershipId)).size !== workspaces.length || new Set(workspaces.map((w) => w.organization.id)).size !== workspaces.length)
|
|
10304
|
-
return
|
|
10720
|
+
return invalid2();
|
|
10305
10721
|
return { workspaces };
|
|
10306
10722
|
}
|
|
10307
10723
|
function parseWorkspaceIdentity(value, expectedUserId) {
|
|
10308
|
-
if (!
|
|
10309
|
-
return
|
|
10724
|
+
if (!record2(value))
|
|
10725
|
+
return invalid2();
|
|
10310
10726
|
const user = value.user;
|
|
10311
|
-
if (!
|
|
10312
|
-
return
|
|
10727
|
+
if (!record2(user) || !uuid2(user.id) || !uuid2(user.membershipId) || !text(user.email, 320) || !(user.displayName === null || text(user.displayName)) || !role2(user.role))
|
|
10728
|
+
return invalid2();
|
|
10313
10729
|
if (user.id !== expectedUserId)
|
|
10314
10730
|
throw new WorkspaceIdentityMismatchError;
|
|
10315
10731
|
return { user: { id: user.id, membershipId: user.membershipId, email: user.email, displayName: user.displayName, role: user.role }, organization: organization(value.organization) };
|
|
10316
10732
|
}
|
|
10317
10733
|
function sessionToken(value) {
|
|
10318
10734
|
if (typeof value !== "string" || !value || value.length > 8192 || /[^\x21-\x7e]/.test(value) || value.startsWith("sk_"))
|
|
10319
|
-
return
|
|
10735
|
+
return invalid2();
|
|
10320
10736
|
return value;
|
|
10321
10737
|
}
|
|
10322
10738
|
function parseWorkspaceSession(value, expected) {
|
|
@@ -10326,9 +10742,9 @@ function parseWorkspaceSession(value, expected) {
|
|
|
10326
10742
|
return { token: sessionToken(value.token), ...identity };
|
|
10327
10743
|
}
|
|
10328
10744
|
function parseWorkspaceLogin(value, expectedUserId) {
|
|
10329
|
-
const user =
|
|
10330
|
-
if (!
|
|
10331
|
-
return
|
|
10745
|
+
const user = record2(value) && value.user;
|
|
10746
|
+
if (!record2(value) || !record2(user) || !uuid2(user.id))
|
|
10747
|
+
return invalid2();
|
|
10332
10748
|
if (expectedUserId !== undefined && user.id !== expectedUserId)
|
|
10333
10749
|
throw new WorkspaceIdentityMismatchError;
|
|
10334
10750
|
return { token: sessionToken(value.token), userId: user.id };
|
|
@@ -10342,18 +10758,18 @@ var workspaceSelectionFailures = {
|
|
|
10342
10758
|
WORKSPACE_BUSY: [503, "Workspace is busy. Refresh before retrying."]
|
|
10343
10759
|
};
|
|
10344
10760
|
function workspaceSelectionFailure(value, status) {
|
|
10345
|
-
if (!
|
|
10761
|
+
if (!record2(value) || typeof value.code !== "string" || !Object.hasOwn(workspaceSelectionFailures, value.code))
|
|
10346
10762
|
return null;
|
|
10347
10763
|
const code = value.code;
|
|
10348
10764
|
return workspaceSelectionFailures[code][0] === status ? code : null;
|
|
10349
10765
|
}
|
|
10350
10766
|
|
|
10351
10767
|
// src/lib/remote-workspace.ts
|
|
10352
|
-
var
|
|
10768
|
+
var record3 = (value) => !!value && typeof value === "object" && !Array.isArray(value);
|
|
10353
10769
|
var cursor = (value) => typeof value === "string" && /^[A-Za-z0-9_-]{1,512}$/.test(value);
|
|
10354
|
-
var
|
|
10770
|
+
var uuid3 = (value) => typeof value === "string" && /^[a-f0-9]{8}-[a-f0-9]{4}-[a-f0-9]{4}-[a-f0-9]{4}-[a-f0-9]{12}$/i.test(value);
|
|
10355
10771
|
function workspaceMembersQuery(options = {}) {
|
|
10356
|
-
if (!
|
|
10772
|
+
if (!record3(options) || Object.keys(options).some((key) => key !== "limit" && key !== "cursor") || options.limit !== undefined && (!Number.isInteger(options.limit) || options.limit < 1 || options.limit > 100) || options.cursor !== undefined && !cursor(options.cursor))
|
|
10357
10773
|
throw new Error("Use a roster limit from 1 to 100 and an unchanged continuation cursor.");
|
|
10358
10774
|
const query = new URLSearchParams;
|
|
10359
10775
|
if (options.limit !== undefined)
|
|
@@ -10362,14 +10778,14 @@ function workspaceMembersQuery(options = {}) {
|
|
|
10362
10778
|
query.set("cursor", options.cursor);
|
|
10363
10779
|
return query.size ? `?${query}` : "";
|
|
10364
10780
|
}
|
|
10365
|
-
function
|
|
10781
|
+
function timestamp2(value) {
|
|
10366
10782
|
if (typeof value !== "string" || !/^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}\.\d{6}Z$/.test(value))
|
|
10367
10783
|
return false;
|
|
10368
10784
|
const time = Date.parse(value);
|
|
10369
10785
|
return Number.isFinite(time) && new Date(time).toISOString().slice(0, 23) === value.slice(0, 23);
|
|
10370
10786
|
}
|
|
10371
10787
|
function parseMember(row, fail) {
|
|
10372
|
-
if (!
|
|
10788
|
+
if (!record3(row) || !uuid3(row.membershipId) || !uuid3(row.userId) || typeof row.email !== "string" || !row.email || !(row.displayName === null || typeof row.displayName === "string") || !isRole(row.role) || !timestamp2(row.createdAt))
|
|
10373
10789
|
return fail();
|
|
10374
10790
|
return {
|
|
10375
10791
|
membershipId: row.membershipId,
|
|
@@ -10389,12 +10805,12 @@ class WorkspaceMemberInputError extends Error {
|
|
|
10389
10805
|
}
|
|
10390
10806
|
}
|
|
10391
10807
|
function mutationInput(membershipId, input, roleChange) {
|
|
10392
|
-
if (typeof membershipId !== "string" || !
|
|
10808
|
+
if (typeof membershipId !== "string" || !uuid3(membershipId) || membershipId !== membershipId.toLowerCase() || !record3(input) || Object.keys(input).sort().join(",") !== (roleChange ? "expectedRole,role" : "expectedRole"))
|
|
10393
10809
|
throw new WorkspaceMemberInputError;
|
|
10394
|
-
const expectedRole = input.expectedRole,
|
|
10395
|
-
if (!isRole(expectedRole) || roleChange && !isRole(
|
|
10810
|
+
const expectedRole = input.expectedRole, role3 = roleChange ? input.role : undefined;
|
|
10811
|
+
if (!isRole(expectedRole) || roleChange && !isRole(role3))
|
|
10396
10812
|
throw new WorkspaceMemberInputError;
|
|
10397
|
-
return { membershipId, role:
|
|
10813
|
+
return { membershipId, role: role3, expectedRole };
|
|
10398
10814
|
}
|
|
10399
10815
|
function workspaceMemberRoleInput(membershipId, input) {
|
|
10400
10816
|
const value = mutationInput(membershipId, input, true);
|
|
@@ -10405,19 +10821,19 @@ function workspaceMemberRemovalInput(membershipId, input) {
|
|
|
10405
10821
|
return { membershipId: value.membershipId, body: { expectedRole: value.expectedRole } };
|
|
10406
10822
|
}
|
|
10407
10823
|
var invalidMemberResult = "The server returned an invalid workspace member result. Refresh the roster before another action.";
|
|
10408
|
-
function parseWorkspaceMemberRoleResult(value, membershipId,
|
|
10824
|
+
function parseWorkspaceMemberRoleResult(value, membershipId, role3) {
|
|
10409
10825
|
const fail = () => {
|
|
10410
10826
|
throw new Error(invalidMemberResult);
|
|
10411
10827
|
};
|
|
10412
|
-
if (!
|
|
10828
|
+
if (!record3(value) || !uuid3(value.organizationId) || typeof value.changed !== "boolean")
|
|
10413
10829
|
return fail();
|
|
10414
10830
|
const member = parseMember(value.member, fail);
|
|
10415
|
-
if (member.membershipId !== membershipId || member.role !==
|
|
10831
|
+
if (member.membershipId !== membershipId || member.role !== role3)
|
|
10416
10832
|
return fail();
|
|
10417
10833
|
return { organizationId: value.organizationId, member, changed: value.changed };
|
|
10418
10834
|
}
|
|
10419
10835
|
function parseWorkspaceMemberRemovalResult(value, membershipId) {
|
|
10420
|
-
if (!
|
|
10836
|
+
if (!record3(value) || !uuid3(value.organizationId) || value.membershipId !== membershipId || value.removed !== true || typeof value.alreadyRemoved !== "boolean")
|
|
10421
10837
|
throw new Error(invalidMemberResult);
|
|
10422
10838
|
return { organizationId: value.organizationId, membershipId, removed: true, alreadyRemoved: value.alreadyRemoved };
|
|
10423
10839
|
}
|
|
@@ -10434,7 +10850,7 @@ var workspaceMemberFailures = {
|
|
|
10434
10850
|
MEMBERSHIP_BUSY: [503, "Membership is busy. Refresh the roster before another action."]
|
|
10435
10851
|
};
|
|
10436
10852
|
function workspaceMemberFailure(value, status) {
|
|
10437
|
-
if (!
|
|
10853
|
+
if (!record3(value) || typeof value.code !== "string" || !Object.hasOwn(workspaceMemberFailures, value.code))
|
|
10438
10854
|
return null;
|
|
10439
10855
|
const code = value.code;
|
|
10440
10856
|
return workspaceMemberFailures[code][0] === status ? code : null;
|
|
@@ -10443,7 +10859,7 @@ function parseWorkspaceMembersPage(value) {
|
|
|
10443
10859
|
const fail = () => {
|
|
10444
10860
|
throw new Error("The server returned an invalid workspace roster.");
|
|
10445
10861
|
};
|
|
10446
|
-
if (!
|
|
10862
|
+
if (!record3(value) || !uuid3(value.organizationId) || !Array.isArray(value.members) || value.members.length > 100 || !(value.nextCursor === null || cursor(value.nextCursor)) || !value.members.length && value.nextCursor !== null)
|
|
10447
10863
|
return fail();
|
|
10448
10864
|
const members = value.members.map((row) => parseMember(row, fail));
|
|
10449
10865
|
if (new Set(members.map((row) => row.membershipId)).size !== members.length)
|
|
@@ -10517,44 +10933,44 @@ function getApiUrl(action, env = process.env, options = {}) {
|
|
|
10517
10933
|
// src/lib/remote-run-contract.ts
|
|
10518
10934
|
var REMOTE_SKILL_RUN_CONTRACT_VERSION = 1;
|
|
10519
10935
|
function normalizeRemoteSkillRunContract(payload, fallbackSkill) {
|
|
10520
|
-
const
|
|
10936
|
+
const record4 = isRecord3(payload) ? payload : {};
|
|
10521
10937
|
return {
|
|
10522
10938
|
contractVersion: REMOTE_SKILL_RUN_CONTRACT_VERSION,
|
|
10523
|
-
...pickString(
|
|
10524
|
-
skill: pickStringValue(
|
|
10525
|
-
...pickString(
|
|
10526
|
-
...pickString(
|
|
10527
|
-
...pickNumber(
|
|
10528
|
-
...pickString(
|
|
10529
|
-
...pickString(
|
|
10530
|
-
...pickString(
|
|
10531
|
-
...pickString(
|
|
10532
|
-
...pickNumber(
|
|
10533
|
-
...pickString(
|
|
10534
|
-
...hasOwn(
|
|
10535
|
-
...pickString(
|
|
10536
|
-
...pickString(
|
|
10537
|
-
...pickString(
|
|
10538
|
-
...pickString(
|
|
10539
|
-
...hasOwn(
|
|
10939
|
+
...pickString(record4, "id"),
|
|
10940
|
+
skill: pickStringValue(record4, "skill") ?? fallbackSkill,
|
|
10941
|
+
...pickString(record4, "requestedSlug"),
|
|
10942
|
+
...pickString(record4, "status"),
|
|
10943
|
+
...pickNumber(record4, "exitCode"),
|
|
10944
|
+
...pickString(record4, "correlationId"),
|
|
10945
|
+
...pickString(record4, "createdAt"),
|
|
10946
|
+
...pickString(record4, "startedAt"),
|
|
10947
|
+
...pickString(record4, "completedAt"),
|
|
10948
|
+
...pickNumber(record4, "durationMs"),
|
|
10949
|
+
...pickString(record4, "outputType"),
|
|
10950
|
+
...hasOwn(record4, "outputPreview") ? { outputPreview: record4.outputPreview } : {},
|
|
10951
|
+
...pickString(record4, "errorCode"),
|
|
10952
|
+
...pickString(record4, "errorMessage"),
|
|
10953
|
+
...pickString(record4, "error"),
|
|
10954
|
+
...pickString(record4, "code"),
|
|
10955
|
+
...hasOwn(record4, "details") ? { details: record4.details } : {}
|
|
10540
10956
|
};
|
|
10541
10957
|
}
|
|
10542
10958
|
function isRecord3(value) {
|
|
10543
10959
|
return Boolean(value && typeof value === "object" && !Array.isArray(value));
|
|
10544
10960
|
}
|
|
10545
|
-
function hasOwn(
|
|
10546
|
-
return Object.prototype.hasOwnProperty.call(
|
|
10961
|
+
function hasOwn(record4, key) {
|
|
10962
|
+
return Object.prototype.hasOwnProperty.call(record4, key);
|
|
10547
10963
|
}
|
|
10548
|
-
function pickString(
|
|
10549
|
-
const value = pickStringValue(
|
|
10964
|
+
function pickString(record4, key) {
|
|
10965
|
+
const value = pickStringValue(record4, key);
|
|
10550
10966
|
return value === undefined ? {} : { [key]: value };
|
|
10551
10967
|
}
|
|
10552
|
-
function pickStringValue(
|
|
10553
|
-
const value =
|
|
10968
|
+
function pickStringValue(record4, key) {
|
|
10969
|
+
const value = record4[key];
|
|
10554
10970
|
return typeof value === "string" ? value : undefined;
|
|
10555
10971
|
}
|
|
10556
|
-
function pickNumber(
|
|
10557
|
-
const value =
|
|
10972
|
+
function pickNumber(record4, key) {
|
|
10973
|
+
const value = record4[key];
|
|
10558
10974
|
return typeof value === "number" && Number.isFinite(value) ? { [key]: value } : {};
|
|
10559
10975
|
}
|
|
10560
10976
|
|
|
@@ -10724,6 +11140,69 @@ function parseUpdatedWorkspace(value) {
|
|
|
10724
11140
|
return { organization: { id: organization2.id, slug: organization2.slug, name: organization2.name } };
|
|
10725
11141
|
}
|
|
10726
11142
|
|
|
11143
|
+
// src/lib/remote-quote-errors.ts
|
|
11144
|
+
var quoteUnavailableMessages = Object.freeze({
|
|
11145
|
+
HOSTED_PROVIDER_UNAVAILABLE: "Hosted execution is temporarily unavailable on this Skills instance.",
|
|
11146
|
+
HOSTED_CONNECTORS_UNAVAILABLE: "Hosted connector execution is unavailable on this Skills instance.",
|
|
11147
|
+
SKILL_IMPLEMENTATION_UNAVAILABLE: "This skill has no hosted execution implementation.",
|
|
11148
|
+
HOSTED_PRICING_UNAVAILABLE: "Hosted execution is unavailable while this skill's pricing is reviewed.",
|
|
11149
|
+
RUNTIME_ALLOWLIST_REQUIRED: "Hosted execution is unavailable until this Skills instance enables its skill catalog.",
|
|
11150
|
+
RUNTIME_SKILL_NOT_ALLOWED: "This skill is not enabled for hosted execution on this Skills instance."
|
|
11151
|
+
});
|
|
11152
|
+
async function readQuoteUnavailableCode(response) {
|
|
11153
|
+
const maximum = 16 * 1024;
|
|
11154
|
+
const length = response.headers.get("content-length");
|
|
11155
|
+
if (response.status !== 503 || response.headers.get("content-type")?.split(";")[0]?.trim().toLowerCase() !== "application/json" || length !== null && (!/^\d+$/.test(length) || Number(length) > maximum)) {
|
|
11156
|
+
response.body?.cancel().catch(() => {});
|
|
11157
|
+
return null;
|
|
11158
|
+
}
|
|
11159
|
+
const reader = response.body?.getReader();
|
|
11160
|
+
if (!reader)
|
|
11161
|
+
return null;
|
|
11162
|
+
let timer;
|
|
11163
|
+
let deadlineExceeded = false;
|
|
11164
|
+
const expired = Symbol("quote body deadline");
|
|
11165
|
+
const deadline = new Promise((resolve2) => {
|
|
11166
|
+
timer = setTimeout(() => {
|
|
11167
|
+
deadlineExceeded = true;
|
|
11168
|
+
resolve2(expired);
|
|
11169
|
+
reader.cancel().catch(() => {});
|
|
11170
|
+
}, 1500);
|
|
11171
|
+
});
|
|
11172
|
+
const chunks = [];
|
|
11173
|
+
let size = 0;
|
|
11174
|
+
try {
|
|
11175
|
+
while (true) {
|
|
11176
|
+
const next = await Promise.race([reader.read(), deadline]);
|
|
11177
|
+
if (next === expired || deadlineExceeded)
|
|
11178
|
+
return null;
|
|
11179
|
+
if (next.done)
|
|
11180
|
+
break;
|
|
11181
|
+
size += next.value.byteLength;
|
|
11182
|
+
if (size > maximum)
|
|
11183
|
+
return null;
|
|
11184
|
+
chunks.push(next.value);
|
|
11185
|
+
}
|
|
11186
|
+
const bytes = new Uint8Array(size);
|
|
11187
|
+
let offset = 0;
|
|
11188
|
+
for (const chunk of chunks) {
|
|
11189
|
+
bytes.set(chunk, offset);
|
|
11190
|
+
offset += chunk.byteLength;
|
|
11191
|
+
}
|
|
11192
|
+
const value = JSON.parse(new TextDecoder("utf-8", { fatal: true }).decode(bytes));
|
|
11193
|
+
if (!value || typeof value !== "object" || Array.isArray(value))
|
|
11194
|
+
return null;
|
|
11195
|
+
const code = value.code;
|
|
11196
|
+
return typeof code === "string" && Object.hasOwn(quoteUnavailableMessages, code) ? code : null;
|
|
11197
|
+
} catch {
|
|
11198
|
+
return null;
|
|
11199
|
+
} finally {
|
|
11200
|
+
clearTimeout(timer);
|
|
11201
|
+
reader.cancel().catch(() => {});
|
|
11202
|
+
reader.releaseLock();
|
|
11203
|
+
}
|
|
11204
|
+
}
|
|
11205
|
+
|
|
10727
11206
|
// src/lib/remote-client.ts
|
|
10728
11207
|
class RemoteRouteUnsupportedError extends Error {
|
|
10729
11208
|
path;
|
|
@@ -10749,6 +11228,18 @@ class RemoteRequestError extends Error {
|
|
|
10749
11228
|
}
|
|
10750
11229
|
}
|
|
10751
11230
|
|
|
11231
|
+
class RemoteQuoteUnavailableError extends RemoteRequestError {
|
|
11232
|
+
code;
|
|
11233
|
+
constructor(path, code) {
|
|
11234
|
+
super(path, 503);
|
|
11235
|
+
this.code = code;
|
|
11236
|
+
if (!Object.hasOwn(quoteUnavailableMessages, code))
|
|
11237
|
+
throw new Error("Unknown quote refusal code");
|
|
11238
|
+
this.name = "RemoteQuoteUnavailableError";
|
|
11239
|
+
this.message = quoteUnavailableMessages[code];
|
|
11240
|
+
}
|
|
11241
|
+
}
|
|
11242
|
+
|
|
10752
11243
|
class RemoteWorkspaceMemberError extends RemoteRequestError {
|
|
10753
11244
|
code;
|
|
10754
11245
|
constructor(path, code) {
|
|
@@ -10810,6 +11301,11 @@ class RemoteSkillsClient {
|
|
|
10810
11301
|
throw new RemoteRouteUnsupportedError(routePath, response.status, this.apiUrl);
|
|
10811
11302
|
}
|
|
10812
11303
|
if (!response.ok) {
|
|
11304
|
+
if (opts.quoteRefusal && options?.method === "POST" && /^\/api\/v1\/skills\/[^/?#]+\/quote$/.test(routePath) && response.status === 503) {
|
|
11305
|
+
const code = await readQuoteUnavailableCode(response);
|
|
11306
|
+
if (code)
|
|
11307
|
+
throw new RemoteQuoteUnavailableError(routePath, code);
|
|
11308
|
+
}
|
|
10813
11309
|
if (path === "/api/v1/billing/checkout" && options?.method === "POST" && response.status === 503 && await responseBodyCarriesCode(response, ["SUBSCRIPTION_CHECKOUT_UNAVAILABLE"])) {
|
|
10814
11310
|
throw new RemoteCapabilityUnavailableError;
|
|
10815
11311
|
}
|
|
@@ -10867,7 +11363,7 @@ class RemoteSkillsClient {
|
|
|
10867
11363
|
const response = await this.requestNewRoute(`/api/v1/skills/${encodeURIComponent(slug)}/quote`, {
|
|
10868
11364
|
method: "POST",
|
|
10869
11365
|
body: JSON.stringify({ input, args })
|
|
10870
|
-
});
|
|
11366
|
+
}, { quoteRefusal: true });
|
|
10871
11367
|
return parseRemoteRunQuote(await response.json());
|
|
10872
11368
|
}
|
|
10873
11369
|
getCapabilities() {
|
|
@@ -11032,6 +11528,53 @@ class RemoteSkillsClient {
|
|
|
11032
11528
|
}
|
|
11033
11529
|
return parseWorkspaceLeaveResult(body, captured.context.membershipId, identity.organization.id);
|
|
11034
11530
|
}
|
|
11531
|
+
listWorkspaceInvitations(context, options = {}) {
|
|
11532
|
+
return this.requestWorkspaceInvitation(context, "list", options);
|
|
11533
|
+
}
|
|
11534
|
+
getWorkspaceInvitation(context, invitationId) {
|
|
11535
|
+
return this.requestWorkspaceInvitation(context, "get", { invitationId });
|
|
11536
|
+
}
|
|
11537
|
+
issueWorkspaceInvitation(context, input) {
|
|
11538
|
+
return this.requestWorkspaceInvitation(context, "issue", input);
|
|
11539
|
+
}
|
|
11540
|
+
resendWorkspaceInvitation(context, invitationId, input) {
|
|
11541
|
+
return this.requestWorkspaceInvitation(context, "resend", { ...input, invitationId });
|
|
11542
|
+
}
|
|
11543
|
+
revokeWorkspaceInvitation(context, invitationId, input) {
|
|
11544
|
+
return this.requestWorkspaceInvitation(context, "revoke", { ...input, invitationId });
|
|
11545
|
+
}
|
|
11546
|
+
acceptWorkspaceInvitation(context, invitationId, input) {
|
|
11547
|
+
return this.requestWorkspaceInvitation(context, "accept", { ...input, invitationId });
|
|
11548
|
+
}
|
|
11549
|
+
async requestWorkspaceInvitation(context, action, input) {
|
|
11550
|
+
const target = workspaceContext(context), captured = invitationInput(action, input);
|
|
11551
|
+
const connection = new RemoteSkillsClient(this.apiKey, this.apiUrl);
|
|
11552
|
+
const identityValue = await connection.requestWorkspaceSelection("/api/auth/whoami");
|
|
11553
|
+
if (!identityValue || typeof identityValue !== "object" || identityValue.authMethod !== "jwt")
|
|
11554
|
+
throw new RemoteWorkspaceInvitationError("INTERACTIVE_SESSION_REQUIRED");
|
|
11555
|
+
const identity = parseWorkspaceIdentity(identityValue, target.userId);
|
|
11556
|
+
if (identity.user.membershipId !== target.membershipId)
|
|
11557
|
+
throw new WorkspaceIdentityMismatchError;
|
|
11558
|
+
const request = invitationRequest(action, captured), read = action === "list" || action === "get";
|
|
11559
|
+
let response, value;
|
|
11560
|
+
try {
|
|
11561
|
+
response = await connection.request(request.path, { method: request.method, ...request.body ? { body: request.body } : {}, credentials: "omit" });
|
|
11562
|
+
value = JSON.parse(new TextDecoder().decode(await readBoundedResponse(response, response.ok ? 64 * 1024 : 4096)));
|
|
11563
|
+
} catch {
|
|
11564
|
+
throw read ? new RemoteWorkspaceInvitationReadError : new RemoteWorkspaceInvitationUnconfirmedError;
|
|
11565
|
+
}
|
|
11566
|
+
if (!response.ok) {
|
|
11567
|
+
const code = invitationFailure(value, response.status);
|
|
11568
|
+
if (code)
|
|
11569
|
+
throw new RemoteWorkspaceInvitationError(code);
|
|
11570
|
+
throw read ? new RemoteWorkspaceInvitationReadError : new RemoteWorkspaceInvitationUnconfirmedError;
|
|
11571
|
+
}
|
|
11572
|
+
try {
|
|
11573
|
+
return parseInvitationResult(action, value, captured, identity.organization.id);
|
|
11574
|
+
} catch {
|
|
11575
|
+
throw read ? new RemoteWorkspaceInvitationReadError : new RemoteWorkspaceInvitationUnconfirmedError;
|
|
11576
|
+
}
|
|
11577
|
+
}
|
|
11035
11578
|
async listApiKeys() {
|
|
11036
11579
|
return this.arrayResponse("/api/auth/keys");
|
|
11037
11580
|
}
|
|
@@ -11282,13 +11825,13 @@ class RemoteSkillsClient {
|
|
|
11282
11825
|
return normalizeUpdatedSincePage(await response.json());
|
|
11283
11826
|
}
|
|
11284
11827
|
}
|
|
11285
|
-
function requireOptionalString(
|
|
11286
|
-
if (
|
|
11828
|
+
function requireOptionalString(record4, field) {
|
|
11829
|
+
if (record4[field] === undefined)
|
|
11287
11830
|
return;
|
|
11288
|
-
if (typeof
|
|
11831
|
+
if (typeof record4[field] !== "string") {
|
|
11289
11832
|
throw new Error(`Remote payload did not match the expected contract (${field} must be a string when present)`);
|
|
11290
11833
|
}
|
|
11291
|
-
return
|
|
11834
|
+
return record4[field];
|
|
11292
11835
|
}
|
|
11293
11836
|
var INVALID_SKILL_VERSION_RESPONSE = "Remote skill version payload did not match the expected contract.";
|
|
11294
11837
|
function isVersionRecord(value) {
|
|
@@ -11311,19 +11854,19 @@ function normalizePin(entry) {
|
|
|
11311
11854
|
if (!entry || typeof entry !== "object") {
|
|
11312
11855
|
throw new Error("Remote pin payload did not match the expected contract (expected an object)");
|
|
11313
11856
|
}
|
|
11314
|
-
const
|
|
11315
|
-
const slug = typeof
|
|
11857
|
+
const record4 = entry;
|
|
11858
|
+
const slug = typeof record4.slug === "string" && record4.slug.trim() ? record4.slug.trim() : undefined;
|
|
11316
11859
|
if (!slug) {
|
|
11317
11860
|
throw new Error("Remote pin payload did not match the expected contract (missing slug)");
|
|
11318
11861
|
}
|
|
11319
11862
|
let metadata;
|
|
11320
|
-
if (
|
|
11321
|
-
if (!
|
|
11863
|
+
if (record4.metadata !== undefined) {
|
|
11864
|
+
if (!record4.metadata || typeof record4.metadata !== "object" || Array.isArray(record4.metadata)) {
|
|
11322
11865
|
throw new Error("Remote pin payload did not match the expected contract (metadata must be a JSON object when present)");
|
|
11323
11866
|
}
|
|
11324
|
-
metadata =
|
|
11867
|
+
metadata = record4.metadata;
|
|
11325
11868
|
}
|
|
11326
|
-
const pinnedAt = requireOptionalString(
|
|
11869
|
+
const pinnedAt = requireOptionalString(record4, "pinnedAt");
|
|
11327
11870
|
return {
|
|
11328
11871
|
slug,
|
|
11329
11872
|
...pinnedAt !== undefined ? { pinnedAt } : {},
|
|
@@ -11340,16 +11883,16 @@ function normalizeSkillSummary(entry) {
|
|
|
11340
11883
|
if (!entry || typeof entry !== "object") {
|
|
11341
11884
|
throw new Error("Remote skill payload did not match the expected contract (expected an object)");
|
|
11342
11885
|
}
|
|
11343
|
-
const
|
|
11344
|
-
const slug = typeof
|
|
11886
|
+
const record4 = entry;
|
|
11887
|
+
const slug = typeof record4.slug === "string" && record4.slug.trim() ? record4.slug.trim() : undefined;
|
|
11345
11888
|
if (!slug) {
|
|
11346
11889
|
throw new Error("Remote skill payload did not match the expected contract (missing slug)");
|
|
11347
11890
|
}
|
|
11348
11891
|
return {
|
|
11349
11892
|
slug,
|
|
11350
|
-
...requireOptionalString(
|
|
11351
|
-
...requireOptionalString(
|
|
11352
|
-
...requireOptionalString(
|
|
11893
|
+
...requireOptionalString(record4, "name") !== undefined ? { name: requireOptionalString(record4, "name") } : {},
|
|
11894
|
+
...requireOptionalString(record4, "version") !== undefined ? { version: requireOptionalString(record4, "version") } : {},
|
|
11895
|
+
...requireOptionalString(record4, "updatedAt") !== undefined ? { updatedAt: requireOptionalString(record4, "updatedAt") } : {}
|
|
11353
11896
|
};
|
|
11354
11897
|
}
|
|
11355
11898
|
function normalizeSkillSummaryList(payload) {
|
|
@@ -11402,12 +11945,12 @@ function normalizeUpdatedSincePage(payload) {
|
|
|
11402
11945
|
if (!payload || typeof payload !== "object") {
|
|
11403
11946
|
throw new Error("Updated-since payload did not match the expected contract (expected an object)");
|
|
11404
11947
|
}
|
|
11405
|
-
const
|
|
11406
|
-
if (!Array.isArray(
|
|
11948
|
+
const record4 = payload;
|
|
11949
|
+
if (!Array.isArray(record4.skills)) {
|
|
11407
11950
|
throw new Error("Updated-since payload did not match the expected contract (missing skills array)");
|
|
11408
11951
|
}
|
|
11409
|
-
const skills =
|
|
11410
|
-
const nextCursor =
|
|
11952
|
+
const skills = record4.skills.map(normalizeSkillSummary);
|
|
11953
|
+
const nextCursor = record4.nextCursor === undefined || record4.nextCursor === null ? null : record4.nextCursor;
|
|
11411
11954
|
if (nextCursor !== null && typeof nextCursor !== "string") {
|
|
11412
11955
|
throw new Error("Updated-since payload did not match the expected contract (nextCursor must be a string or absent)");
|
|
11413
11956
|
}
|
|
@@ -11621,10 +12164,6 @@ function recordScheduleRun(id, status, targetDir) {
|
|
|
11621
12164
|
schedule.nextRun = getNextRun(schedule.cron, now)?.toISOString();
|
|
11622
12165
|
saveSchedules(data, targetDir);
|
|
11623
12166
|
}
|
|
11624
|
-
// src/lib/pull.ts
|
|
11625
|
-
import { existsSync as existsSync15, mkdirSync as mkdirSync8, mkdtempSync as mkdtempSync3, readFileSync as readFileSync15, renameSync as renameSync3, rmSync as rmSync4, writeFileSync as writeFileSync8 } from "fs";
|
|
11626
|
-
import { dirname as dirname6, join as join17 } from "path";
|
|
11627
|
-
|
|
11628
12167
|
// src/lib/revision.ts
|
|
11629
12168
|
import { createHash as createHash4 } from "crypto";
|
|
11630
12169
|
var REVISION_ID_PATTERN = /^[0-9a-f]{64}$/;
|
|
@@ -11644,14 +12183,18 @@ function revisionIdOf(content) {
|
|
|
11644
12183
|
});
|
|
11645
12184
|
return createHash4("sha256").update(canonical).digest("hex");
|
|
11646
12185
|
}
|
|
11647
|
-
function revisionIdOfRecord(
|
|
11648
|
-
return revisionIdOf(
|
|
12186
|
+
function revisionIdOfRecord(record4) {
|
|
12187
|
+
return revisionIdOf(record4);
|
|
11649
12188
|
}
|
|
12189
|
+
// src/lib/pull.ts
|
|
12190
|
+
import { existsSync as existsSync15, mkdirSync as mkdirSync8, mkdtempSync as mkdtempSync3, readFileSync as readFileSync15, renameSync as renameSync3, rmSync as rmSync4, writeFileSync as writeFileSync8 } from "fs";
|
|
12191
|
+
import { dirname as dirname6, join as join17 } from "path";
|
|
11650
12192
|
|
|
11651
12193
|
// src/lib/skill-bundle.ts
|
|
11652
12194
|
import { createHash as createHash5 } from "crypto";
|
|
11653
12195
|
import { readFileSync as readFileSync14, readdirSync as readdirSync9, statSync as statSync9 } from "fs";
|
|
11654
12196
|
import { join as join16, relative as relative3 } from "path";
|
|
12197
|
+
import { createGunzip } from "zlib";
|
|
11655
12198
|
var BLOCK = 512;
|
|
11656
12199
|
var ANY_SEGMENT_EXCLUDES = new Set([
|
|
11657
12200
|
".git",
|
|
@@ -11974,6 +12517,227 @@ function concat(chunks) {
|
|
|
11974
12517
|
}
|
|
11975
12518
|
return merged;
|
|
11976
12519
|
}
|
|
12520
|
+
var SKILL_BUNDLE_INSPECTION_LIMITS = Object.freeze({
|
|
12521
|
+
compressedBytes: 16 * 1024 * 1024,
|
|
12522
|
+
decompressedBytes: 64 * 1024 * 1024,
|
|
12523
|
+
entries: 1024,
|
|
12524
|
+
fileBytes: 16 * 1024 * 1024,
|
|
12525
|
+
pathBytes: 100,
|
|
12526
|
+
timeoutMs: 5000
|
|
12527
|
+
});
|
|
12528
|
+
|
|
12529
|
+
class SkillBundleInspectionError extends Error {
|
|
12530
|
+
code;
|
|
12531
|
+
constructor(code, message) {
|
|
12532
|
+
super(message);
|
|
12533
|
+
this.code = code;
|
|
12534
|
+
this.name = "SkillBundleInspectionError";
|
|
12535
|
+
}
|
|
12536
|
+
}
|
|
12537
|
+
function invalidBundle(message) {
|
|
12538
|
+
throw new SkillBundleInspectionError("BUNDLE_INVALID", message);
|
|
12539
|
+
}
|
|
12540
|
+
function inspectionLimits(options) {
|
|
12541
|
+
const limits = { ...SKILL_BUNDLE_INSPECTION_LIMITS };
|
|
12542
|
+
for (const key of Object.keys(options.limits ?? {})) {
|
|
12543
|
+
if (!Object.hasOwn(limits, key))
|
|
12544
|
+
throw new SkillBundleInspectionError("BUNDLE_LIMIT", "Unknown bundle limit");
|
|
12545
|
+
const field = key;
|
|
12546
|
+
const value = options.limits[field];
|
|
12547
|
+
if (!Number.isSafeInteger(value) || value <= 0 || value > limits[field]) {
|
|
12548
|
+
throw new SkillBundleInspectionError("BUNDLE_LIMIT", "Bundle limits must be positive integers within the hard ceilings");
|
|
12549
|
+
}
|
|
12550
|
+
limits[field] = value;
|
|
12551
|
+
}
|
|
12552
|
+
return limits;
|
|
12553
|
+
}
|
|
12554
|
+
async function inspectSkillBundle(bundle, options = {}) {
|
|
12555
|
+
const signal = options.signal;
|
|
12556
|
+
const limits = inspectionLimits(options);
|
|
12557
|
+
const deadline = performance.now() + limits.timeoutMs;
|
|
12558
|
+
const check = () => {
|
|
12559
|
+
if (signal?.aborted)
|
|
12560
|
+
throw new SkillBundleInspectionError("BUNDLE_ABORTED", "Bundle inspection aborted");
|
|
12561
|
+
if (performance.now() >= deadline)
|
|
12562
|
+
throw new SkillBundleInspectionError("BUNDLE_TIMEOUT", "Bundle inspection deadline exceeded");
|
|
12563
|
+
};
|
|
12564
|
+
check();
|
|
12565
|
+
if (bundle.byteLength > limits.compressedBytes)
|
|
12566
|
+
throw new SkillBundleInspectionError("BUNDLE_LIMIT", "Compressed bundle exceeds byte limit");
|
|
12567
|
+
const snapshot = ownBytes(bundle);
|
|
12568
|
+
check();
|
|
12569
|
+
const sha2562 = sha256Hex(snapshot);
|
|
12570
|
+
check();
|
|
12571
|
+
const parser = new BoundedTarReader(limits, check);
|
|
12572
|
+
const streamOptions = { chunkSize: 16 * 1024, highWaterMark: 16 * 1024 };
|
|
12573
|
+
const decoder = createGunzip(streamOptions);
|
|
12574
|
+
let terminalError;
|
|
12575
|
+
const stop = (code) => {
|
|
12576
|
+
terminalError ??= new SkillBundleInspectionError(code, code === "BUNDLE_ABORTED" ? "Bundle inspection aborted" : "Bundle inspection deadline exceeded");
|
|
12577
|
+
decoder.destroy(terminalError);
|
|
12578
|
+
};
|
|
12579
|
+
const onAbort = () => stop("BUNDLE_ABORTED");
|
|
12580
|
+
const timer = setTimeout(() => stop("BUNDLE_TIMEOUT"), Math.max(1, deadline - performance.now()));
|
|
12581
|
+
signal?.addEventListener("abort", onAbort, { once: true });
|
|
12582
|
+
let decompressedByteSize = 0;
|
|
12583
|
+
let bytesSinceYield = 0;
|
|
12584
|
+
try {
|
|
12585
|
+
check();
|
|
12586
|
+
decoder.end(snapshot);
|
|
12587
|
+
for await (const chunk of decoder) {
|
|
12588
|
+
check();
|
|
12589
|
+
decompressedByteSize += chunk.byteLength;
|
|
12590
|
+
if (decompressedByteSize > limits.decompressedBytes)
|
|
12591
|
+
throw new SkillBundleInspectionError("BUNDLE_LIMIT", "Decompressed bundle exceeds byte limit");
|
|
12592
|
+
parser.push(chunk);
|
|
12593
|
+
bytesSinceYield += chunk.byteLength;
|
|
12594
|
+
if (bytesSinceYield >= 256 * 1024) {
|
|
12595
|
+
await new Promise((resolve2) => setTimeout(resolve2, 0));
|
|
12596
|
+
bytesSinceYield = 0;
|
|
12597
|
+
check();
|
|
12598
|
+
}
|
|
12599
|
+
}
|
|
12600
|
+
check();
|
|
12601
|
+
const entries = parser.finish();
|
|
12602
|
+
return {
|
|
12603
|
+
entries,
|
|
12604
|
+
sha256: sha2562,
|
|
12605
|
+
compressedByteSize: snapshot.byteLength,
|
|
12606
|
+
decompressedByteSize,
|
|
12607
|
+
unpackedByteSize: parser.fileBytes,
|
|
12608
|
+
fileCount: entries.length
|
|
12609
|
+
};
|
|
12610
|
+
} catch (error) {
|
|
12611
|
+
if (terminalError)
|
|
12612
|
+
throw terminalError;
|
|
12613
|
+
if (error instanceof SkillBundleInspectionError)
|
|
12614
|
+
throw error;
|
|
12615
|
+
throw new SkillBundleInspectionError("BUNDLE_INVALID", "Invalid or truncated gzip bundle");
|
|
12616
|
+
} finally {
|
|
12617
|
+
clearTimeout(timer);
|
|
12618
|
+
signal?.removeEventListener("abort", onAbort);
|
|
12619
|
+
decoder.destroy();
|
|
12620
|
+
}
|
|
12621
|
+
}
|
|
12622
|
+
|
|
12623
|
+
class BoundedTarReader {
|
|
12624
|
+
limits;
|
|
12625
|
+
check;
|
|
12626
|
+
header = new Uint8Array(BLOCK);
|
|
12627
|
+
headerOffset = 0;
|
|
12628
|
+
pending;
|
|
12629
|
+
bodyOffset = 0;
|
|
12630
|
+
padding = 0;
|
|
12631
|
+
zeroBlocks = 0;
|
|
12632
|
+
entries = [];
|
|
12633
|
+
paths = new SkillEntryPaths;
|
|
12634
|
+
fileBytes = 0;
|
|
12635
|
+
constructor(limits, check) {
|
|
12636
|
+
this.limits = limits;
|
|
12637
|
+
this.check = check;
|
|
12638
|
+
}
|
|
12639
|
+
push(chunk) {
|
|
12640
|
+
let offset = 0;
|
|
12641
|
+
while (offset < chunk.byteLength) {
|
|
12642
|
+
this.check();
|
|
12643
|
+
if (this.pending) {
|
|
12644
|
+
const count = Math.min(this.pending.bytes.byteLength - this.bodyOffset, chunk.byteLength - offset);
|
|
12645
|
+
this.pending.bytes.set(chunk.subarray(offset, offset + count), this.bodyOffset);
|
|
12646
|
+
offset += count;
|
|
12647
|
+
this.bodyOffset += count;
|
|
12648
|
+
if (this.bodyOffset === this.pending.bytes.byteLength) {
|
|
12649
|
+
this.entries.push(this.pending);
|
|
12650
|
+
this.pending = undefined;
|
|
12651
|
+
}
|
|
12652
|
+
} else if (this.padding) {
|
|
12653
|
+
const count = Math.min(this.padding, chunk.byteLength - offset);
|
|
12654
|
+
if (chunk.subarray(offset, offset + count).some((byte) => byte !== 0))
|
|
12655
|
+
invalidBundle("Nonzero tar body padding");
|
|
12656
|
+
offset += count;
|
|
12657
|
+
this.padding -= count;
|
|
12658
|
+
} else {
|
|
12659
|
+
const count = Math.min(BLOCK - this.headerOffset, chunk.byteLength - offset);
|
|
12660
|
+
this.header.set(chunk.subarray(offset, offset + count), this.headerOffset);
|
|
12661
|
+
offset += count;
|
|
12662
|
+
this.headerOffset += count;
|
|
12663
|
+
if (this.headerOffset === BLOCK) {
|
|
12664
|
+
this.readHeader();
|
|
12665
|
+
this.headerOffset = 0;
|
|
12666
|
+
}
|
|
12667
|
+
}
|
|
12668
|
+
}
|
|
12669
|
+
}
|
|
12670
|
+
finish() {
|
|
12671
|
+
this.check();
|
|
12672
|
+
if (this.pending || this.padding || this.headerOffset || this.zeroBlocks < 2)
|
|
12673
|
+
invalidBundle("Truncated tar bundle");
|
|
12674
|
+
return this.entries;
|
|
12675
|
+
}
|
|
12676
|
+
readHeader() {
|
|
12677
|
+
this.check();
|
|
12678
|
+
const h = this.header;
|
|
12679
|
+
if (h.every((byte) => byte === 0)) {
|
|
12680
|
+
this.zeroBlocks++;
|
|
12681
|
+
return;
|
|
12682
|
+
}
|
|
12683
|
+
if (this.zeroBlocks)
|
|
12684
|
+
invalidBundle("Nonzero tar data after terminator");
|
|
12685
|
+
if (this.entries.length >= this.limits.entries)
|
|
12686
|
+
throw new SkillBundleInspectionError("BUNDLE_LIMIT", "Bundle entry limit exceeded");
|
|
12687
|
+
let checksum = 0;
|
|
12688
|
+
for (let i = 0;i < BLOCK; i++)
|
|
12689
|
+
checksum += i >= 148 && i < 156 ? 32 : h[i];
|
|
12690
|
+
if (tarOctal(h.subarray(148, 156)) !== checksum)
|
|
12691
|
+
invalidBundle("Invalid tar header checksum");
|
|
12692
|
+
if (new TextDecoder().decode(h.subarray(257, 265)) !== "ustar\x00" + "00")
|
|
12693
|
+
invalidBundle("Unsupported tar format");
|
|
12694
|
+
if (h[156] !== 48 && h[156] !== 0 || h.subarray(157, 257).some((b) => b !== 0) || h.subarray(345).some((b) => b !== 0))
|
|
12695
|
+
invalidBundle("Unsupported tar entry or path prefix");
|
|
12696
|
+
const mode = tarOctal(h.subarray(100, 108));
|
|
12697
|
+
if (mode > 511)
|
|
12698
|
+
invalidBundle("Unsupported tar permission bits");
|
|
12699
|
+
tarOctal(h.subarray(108, 116));
|
|
12700
|
+
tarOctal(h.subarray(116, 124));
|
|
12701
|
+
tarOctal(h.subarray(136, 148));
|
|
12702
|
+
const size = tarOctal(h.subarray(124, 136));
|
|
12703
|
+
if (size > this.limits.fileBytes || this.fileBytes + size > this.limits.decompressedBytes) {
|
|
12704
|
+
throw new SkillBundleInspectionError("BUNDLE_LIMIT", "Bundle file byte limit exceeded");
|
|
12705
|
+
}
|
|
12706
|
+
const name = h.subarray(0, 100);
|
|
12707
|
+
const end = name.indexOf(0);
|
|
12708
|
+
if (end !== -1 && name.subarray(end).some((b) => b !== 0))
|
|
12709
|
+
invalidBundle("Invalid tar path padding");
|
|
12710
|
+
const raw = end === -1 ? name : name.subarray(0, end);
|
|
12711
|
+
if (raw.byteLength > this.limits.pathBytes)
|
|
12712
|
+
throw new SkillBundleInspectionError("BUNDLE_LIMIT", "Bundle path byte limit exceeded");
|
|
12713
|
+
let path;
|
|
12714
|
+
try {
|
|
12715
|
+
path = new TextDecoder("utf-8", { fatal: true, ignoreBOM: true }).decode(raw);
|
|
12716
|
+
} catch {
|
|
12717
|
+
return invalidBundle("Invalid UTF-8 bundle path");
|
|
12718
|
+
}
|
|
12719
|
+
this.paths.add(path, this.limits.pathBytes, invalidBundle, () => {
|
|
12720
|
+
throw new SkillBundleInspectionError("BUNDLE_LIMIT", "Bundle path byte limit exceeded");
|
|
12721
|
+
});
|
|
12722
|
+
this.fileBytes += size;
|
|
12723
|
+
this.pending = { path, mode, bytes: new Uint8Array(new ArrayBuffer(size)) };
|
|
12724
|
+
this.bodyOffset = 0;
|
|
12725
|
+
this.padding = (BLOCK - size % BLOCK) % BLOCK;
|
|
12726
|
+
if (!size) {
|
|
12727
|
+
this.entries.push(this.pending);
|
|
12728
|
+
this.pending = undefined;
|
|
12729
|
+
}
|
|
12730
|
+
}
|
|
12731
|
+
}
|
|
12732
|
+
function tarOctal(field) {
|
|
12733
|
+
const text2 = new TextDecoder().decode(field);
|
|
12734
|
+
if (!/^[0-7]+[\0 ]*$/.test(text2))
|
|
12735
|
+
invalidBundle("Invalid tar octal field");
|
|
12736
|
+
const value = Number.parseInt(text2, 8);
|
|
12737
|
+
if (!Number.isSafeInteger(value))
|
|
12738
|
+
invalidBundle("Tar integer is out of range");
|
|
12739
|
+
return value;
|
|
12740
|
+
}
|
|
11977
12741
|
|
|
11978
12742
|
// src/lib/skill-version.ts
|
|
11979
12743
|
var SKILL_VERSION_PATTERN = /^[A-Za-z0-9][A-Za-z0-9._+-]{0,127}$/;
|
|
@@ -12352,16 +13116,16 @@ function installBundleAtomically(name, entries, options = {}, marker = {}) {
|
|
|
12352
13116
|
}
|
|
12353
13117
|
return { path: target, created };
|
|
12354
13118
|
}
|
|
12355
|
-
function writePullMarker(dir,
|
|
13119
|
+
function writePullMarker(dir, record4) {
|
|
12356
13120
|
const marker = {
|
|
12357
13121
|
managedBy: "@hasna/skills",
|
|
12358
|
-
skill:
|
|
12359
|
-
source:
|
|
12360
|
-
...
|
|
12361
|
-
...
|
|
12362
|
-
...
|
|
12363
|
-
...
|
|
12364
|
-
...
|
|
13122
|
+
skill: record4.skill,
|
|
13123
|
+
source: record4.source ?? "pull",
|
|
13124
|
+
...record4.version ? { version: record4.version } : {},
|
|
13125
|
+
...record4.contentHash ? { contentHash: record4.contentHash } : {},
|
|
13126
|
+
...record4.sourceCommit ? { sourceCommit: record4.sourceCommit } : {},
|
|
13127
|
+
...record4.signature ? { signature: record4.signature } : {},
|
|
13128
|
+
...record4.revisionId ? { revisionId: record4.revisionId } : {},
|
|
12365
13129
|
syncedAt: new Date().toISOString()
|
|
12366
13130
|
};
|
|
12367
13131
|
writeFileSync8(join17(dir, PULL_MARKER_FILE), `${JSON.stringify(marker, null, 2)}
|
|
@@ -12376,19 +13140,19 @@ async function safeMeta(client, slug) {
|
|
|
12376
13140
|
}
|
|
12377
13141
|
if (!raw || typeof raw !== "object")
|
|
12378
13142
|
return null;
|
|
12379
|
-
const
|
|
12380
|
-
const kind =
|
|
12381
|
-
const tags = Array.isArray(
|
|
13143
|
+
const record4 = raw;
|
|
13144
|
+
const kind = record4.kind === "instruction" || record4.kind === "executable" ? record4.kind : undefined;
|
|
13145
|
+
const tags = Array.isArray(record4.tags) ? record4.tags.filter((tag) => typeof tag === "string" && tag.trim().length > 0) : undefined;
|
|
12382
13146
|
return {
|
|
12383
|
-
...str(
|
|
12384
|
-
...str(
|
|
12385
|
-
...str(
|
|
13147
|
+
...str(record4.displayName) ? { displayName: str(record4.displayName) } : {},
|
|
13148
|
+
...str(record4.description) ? { description: str(record4.description) } : {},
|
|
13149
|
+
...str(record4.category) ? { category: str(record4.category) } : {},
|
|
12386
13150
|
...tags && tags.length ? { tags } : {},
|
|
12387
|
-
...str(
|
|
13151
|
+
...str(record4.version) ? { version: str(record4.version) } : {},
|
|
12388
13152
|
...kind ? { kind } : {},
|
|
12389
|
-
...REVISION_ID_PATTERN.test(str(
|
|
12390
|
-
...typeof
|
|
12391
|
-
...str(
|
|
13153
|
+
...REVISION_ID_PATTERN.test(str(record4.revisionId) ?? "") ? { revisionId: str(record4.revisionId) } : {},
|
|
13154
|
+
...typeof record4.skillMd === "string" && record4.skillMd.length > 0 ? { skillMd: record4.skillMd } : {},
|
|
13155
|
+
...str(record4.publishedSource) ? { publishedSource: str(record4.publishedSource) } : {}
|
|
12392
13156
|
};
|
|
12393
13157
|
}
|
|
12394
13158
|
function pickCorpusOptions(options) {
|
|
@@ -12397,8 +13161,8 @@ function pickCorpusOptions(options) {
|
|
|
12397
13161
|
function extractSlug(entry) {
|
|
12398
13162
|
if (!entry || typeof entry !== "object")
|
|
12399
13163
|
return;
|
|
12400
|
-
const
|
|
12401
|
-
return str(
|
|
13164
|
+
const record4 = entry;
|
|
13165
|
+
return str(record4.slug) ?? str(record4.name);
|
|
12402
13166
|
}
|
|
12403
13167
|
function dedupe(values) {
|
|
12404
13168
|
return [...new Set(values)];
|
|
@@ -12524,7 +13288,7 @@ import { dirname as dirname7, relative as relative4 } from "path";
|
|
|
12524
13288
|
// package.json
|
|
12525
13289
|
var package_default = {
|
|
12526
13290
|
name: "@hasna/skills",
|
|
12527
|
-
version: "0.5.
|
|
13291
|
+
version: "0.5.4",
|
|
12528
13292
|
description: "Skills library for AI coding agents",
|
|
12529
13293
|
type: "module",
|
|
12530
13294
|
bin: {
|
|
@@ -14035,7 +14799,7 @@ class SkillsPostgresSyncStore {
|
|
|
14035
14799
|
}
|
|
14036
14800
|
async upsertRecords(records) {
|
|
14037
14801
|
let count = 0;
|
|
14038
|
-
for (const
|
|
14802
|
+
for (const record4 of records) {
|
|
14039
14803
|
await this.client.query([
|
|
14040
14804
|
"INSERT INTO skills_sync_records",
|
|
14041
14805
|
"(scope, kind, id, updated_at, deleted_at, source, payload)",
|
|
@@ -14046,13 +14810,13 @@ class SkillsPostgresSyncStore {
|
|
|
14046
14810
|
"source = EXCLUDED.source,",
|
|
14047
14811
|
"payload = EXCLUDED.payload"
|
|
14048
14812
|
].join(" "), [
|
|
14049
|
-
|
|
14050
|
-
|
|
14051
|
-
|
|
14052
|
-
|
|
14053
|
-
|
|
14054
|
-
|
|
14055
|
-
JSON.stringify(
|
|
14813
|
+
record4.scope,
|
|
14814
|
+
record4.kind,
|
|
14815
|
+
record4.id,
|
|
14816
|
+
record4.updatedAt,
|
|
14817
|
+
record4.deletedAt ?? null,
|
|
14818
|
+
record4.source ?? null,
|
|
14819
|
+
JSON.stringify(record4.payload)
|
|
14056
14820
|
]);
|
|
14057
14821
|
count += 1;
|
|
14058
14822
|
}
|
|
@@ -14994,6 +15758,101 @@ function writeStationHydration(options) {
|
|
|
14994
15758
|
manifestPath: hydrationManifestPath
|
|
14995
15759
|
};
|
|
14996
15760
|
}
|
|
15761
|
+
// src/lib/remote-invitation-recovery.ts
|
|
15762
|
+
class InvitationEmailInputError extends Error {
|
|
15763
|
+
code = "INVITATION_EMAIL_INPUT_INVALID";
|
|
15764
|
+
constructor() {
|
|
15765
|
+
super("Use an explicit Skills API URL, exact invitation and retained challenge IDs, secret input, and deliberate confirmation.");
|
|
15766
|
+
this.name = "InvitationEmailInputError";
|
|
15767
|
+
}
|
|
15768
|
+
}
|
|
15769
|
+
var refusals = {
|
|
15770
|
+
INVALID_REQUEST: [400, "Invitation recovery parameters were refused."],
|
|
15771
|
+
ORIGIN_REQUIRED: [403, "Invitation recovery requires the configured site origin."],
|
|
15772
|
+
INVITATION_PROOF_UNAVAILABLE: [401, "Invitation proof is unavailable. Sign in or explicitly request another recovery code."],
|
|
15773
|
+
RATE_LIMITED: [429, "Invitation verification is rate limited. Wait before another deliberate action."],
|
|
15774
|
+
INVITATION_BUSY: [503, "Invitation is busy. Sign in to check membership before another deliberate action."],
|
|
15775
|
+
INVITATION_DELIVERY_UNAVAILABLE: [503, "Invitation recovery is unavailable on this service."]
|
|
15776
|
+
};
|
|
15777
|
+
|
|
15778
|
+
class RemoteInvitationEmailError extends Error {
|
|
15779
|
+
code;
|
|
15780
|
+
status;
|
|
15781
|
+
constructor(code) {
|
|
15782
|
+
super(refusals[code][1]);
|
|
15783
|
+
this.code = code;
|
|
15784
|
+
this.name = "RemoteInvitationEmailError";
|
|
15785
|
+
this.status = refusals[code][0];
|
|
15786
|
+
}
|
|
15787
|
+
}
|
|
15788
|
+
|
|
15789
|
+
class RemoteInvitationEmailUnconfirmedError extends Error {
|
|
15790
|
+
action;
|
|
15791
|
+
code = "INVITATION_EMAIL_UNCONFIRMED";
|
|
15792
|
+
constructor(action) {
|
|
15793
|
+
super(action === "challenge" ? "The recovery challenge outcome is unconfirmed. Retain the same invitation, challenge ID and server. Check your inbox; never rotate the challenge or retry automatically. No delivery is confirmed." : "Invitation acceptance is unconfirmed. Use fresh ordinary sign-in to inspect available memberships. Do not retry acceptance automatically; explicitly request another recovery code only if needed. Saved credentials are unchanged.");
|
|
15794
|
+
this.action = action;
|
|
15795
|
+
this.name = "RemoteInvitationEmailUnconfirmedError";
|
|
15796
|
+
}
|
|
15797
|
+
}
|
|
15798
|
+
var record4 = (v) => !!v && typeof v === "object" && !Array.isArray(v);
|
|
15799
|
+
var uuid4 = (v) => typeof v === "string" && /^[a-f0-9]{8}-[a-f0-9]{4}-[a-f0-9]{4}-[a-f0-9]{4}-[a-f0-9]{12}$/.test(v);
|
|
15800
|
+
function invitationEmailIds(invitationId, challengeId) {
|
|
15801
|
+
if (!uuid4(invitationId) || !uuid4(challengeId))
|
|
15802
|
+
throw new InvitationEmailInputError;
|
|
15803
|
+
return { invitationId, challengeId };
|
|
15804
|
+
}
|
|
15805
|
+
function invitationEmailInput(action, input) {
|
|
15806
|
+
const keys = ["invitationId", "token", "challengeId", "confirm", ...action === "accept" ? ["code"] : []];
|
|
15807
|
+
if (!record4(input) || Object.keys(input).length !== keys.length || keys.some((key) => !Object.hasOwn(input, key)))
|
|
15808
|
+
throw new InvitationEmailInputError;
|
|
15809
|
+
const value = { ...input };
|
|
15810
|
+
const ids = invitationEmailIds(value.invitationId, value.challengeId);
|
|
15811
|
+
if (value.confirm !== true || typeof value.token !== "string" || !/^[A-Za-z0-9_-]{43}$/.test(value.token) || action === "accept" && (typeof value.code !== "string" || !/^\d{6}$/.test(value.code)))
|
|
15812
|
+
throw new InvitationEmailInputError;
|
|
15813
|
+
return { ...ids, token: value.token, confirm: true, ...action === "accept" ? { code: value.code } : {} };
|
|
15814
|
+
}
|
|
15815
|
+
async function requestInvitationEmail(origin, action, input) {
|
|
15816
|
+
const value = invitationEmailInput(action, input);
|
|
15817
|
+
let target;
|
|
15818
|
+
try {
|
|
15819
|
+
target = normalizeSkillsApiOrigin(origin);
|
|
15820
|
+
} catch {
|
|
15821
|
+
throw new InvitationEmailInputError;
|
|
15822
|
+
}
|
|
15823
|
+
const body = JSON.stringify({ invitationId: value.invitationId, token: value.token, challengeId: value.challengeId, ...action === "accept" ? { code: value.code } : {} });
|
|
15824
|
+
try {
|
|
15825
|
+
const response = await fetch(`${target}/api/v1/account/invitations/email-${action}`, {
|
|
15826
|
+
method: "POST",
|
|
15827
|
+
headers: { "Content-Type": "application/json" },
|
|
15828
|
+
body,
|
|
15829
|
+
credentials: "omit",
|
|
15830
|
+
redirect: "error",
|
|
15831
|
+
cache: "no-store",
|
|
15832
|
+
referrerPolicy: "no-referrer",
|
|
15833
|
+
signal: AbortSignal.timeout(15000)
|
|
15834
|
+
});
|
|
15835
|
+
const parsed = JSON.parse(new TextDecoder("utf-8", { fatal: true }).decode(await readBoundedResponse(response, 4096)));
|
|
15836
|
+
if (!response.ok && record4(parsed) && typeof parsed.code === "string" && Object.hasOwn(refusals, parsed.code)) {
|
|
15837
|
+
const code = parsed.code;
|
|
15838
|
+
if (response.status === refusals[code][0])
|
|
15839
|
+
throw new RemoteInvitationEmailError(code);
|
|
15840
|
+
}
|
|
15841
|
+
if (!record4(parsed))
|
|
15842
|
+
throw new RemoteInvitationEmailUnconfirmedError(action);
|
|
15843
|
+
if (action === "challenge" && response.status === 202 && parsed.challengeId === value.challengeId && parsed.expiresIn === 600 && typeof parsed.message === "string" && parsed.message.length <= 256) {
|
|
15844
|
+
return { challengeId: value.challengeId, message: "If this invitation is eligible, a verification code will arrive. Delivery is not confirmed.", expiresIn: 600 };
|
|
15845
|
+
}
|
|
15846
|
+
if (action === "accept" && response.status === 200 && uuid4(parsed.organizationId) && uuid4(parsed.membershipId) && parsed.accepted === true && parsed.changed === true && parsed.signInRequired === true) {
|
|
15847
|
+
return { organizationId: parsed.organizationId, membershipId: parsed.membershipId, accepted: true, changed: true, signInRequired: true };
|
|
15848
|
+
}
|
|
15849
|
+
} catch (error) {
|
|
15850
|
+
if (error instanceof RemoteInvitationEmailError)
|
|
15851
|
+
throw error;
|
|
15852
|
+
}
|
|
15853
|
+
throw new RemoteInvitationEmailUnconfirmedError(action);
|
|
15854
|
+
}
|
|
15855
|
+
|
|
14997
15856
|
// src/lib/remote-auth.ts
|
|
14998
15857
|
var MAX_ERROR_DETAIL_LENGTH = 200;
|
|
14999
15858
|
|
|
@@ -15034,10 +15893,10 @@ async function requestAuthApi(instance, path, options) {
|
|
|
15034
15893
|
const text2 = await res.text();
|
|
15035
15894
|
const body = text2 ? parseJsonBody(text2) : {};
|
|
15036
15895
|
if (!res.ok) {
|
|
15037
|
-
const
|
|
15038
|
-
const detail = typeof
|
|
15039
|
-
const error = typeof
|
|
15040
|
-
const code = typeof
|
|
15896
|
+
const record5 = isRecord5(body) ? body : {};
|
|
15897
|
+
const detail = typeof record5.detail === "string" ? record5.detail : undefined;
|
|
15898
|
+
const error = typeof record5.error === "string" ? record5.error : undefined;
|
|
15899
|
+
const code = typeof record5.code === "string" ? record5.code : undefined;
|
|
15041
15900
|
throw new HostedApiError(detail || error || `${res.status} ${res.statusText}`, {
|
|
15042
15901
|
status: res.status,
|
|
15043
15902
|
code,
|
|
@@ -15071,11 +15930,17 @@ class RemoteSkillsAuthClient {
|
|
|
15071
15930
|
constructor(apiUrl) {
|
|
15072
15931
|
this.apiOrigin = normalizeSkillsApiOrigin(apiUrl);
|
|
15073
15932
|
}
|
|
15074
|
-
|
|
15075
|
-
return this.
|
|
15933
|
+
requestInvitationEmailChallenge(input) {
|
|
15934
|
+
return requestInvitationEmail(this.apiOrigin, "challenge", input);
|
|
15935
|
+
}
|
|
15936
|
+
acceptInvitationEmailChallenge(input) {
|
|
15937
|
+
return requestInvitationEmail(this.apiOrigin, "accept", input);
|
|
15076
15938
|
}
|
|
15077
|
-
|
|
15078
|
-
return this.request("/api/auth/
|
|
15939
|
+
requestCode(email2) {
|
|
15940
|
+
return this.request("/api/auth/login", { method: "POST", body: JSON.stringify({ email: email2 }) });
|
|
15941
|
+
}
|
|
15942
|
+
verifyCode(email2, code) {
|
|
15943
|
+
return this.request("/api/auth/verify", { method: "POST", body: JSON.stringify({ email: email2, code }) });
|
|
15079
15944
|
}
|
|
15080
15945
|
startDevice() {
|
|
15081
15946
|
return this.request("/api/auth/device/start", { method: "POST", body: JSON.stringify({ client: "skills-sdk" }) });
|
|
@@ -15083,34 +15948,34 @@ class RemoteSkillsAuthClient {
|
|
|
15083
15948
|
pollDevice(deviceCode) {
|
|
15084
15949
|
return this.request("/api/auth/device/token", { method: "POST", body: JSON.stringify({ deviceCode }) });
|
|
15085
15950
|
}
|
|
15086
|
-
async sessionClient(
|
|
15951
|
+
async sessionClient(email2, code, context) {
|
|
15087
15952
|
if (context !== undefined) {
|
|
15088
15953
|
const target = workspaceContext(context), apiOrigin2 = this.apiOrigin;
|
|
15089
|
-
const session = await this.switchWorkspace(
|
|
15954
|
+
const session = await this.switchWorkspace(email2, code, target);
|
|
15090
15955
|
return new RemoteSkillsClient(session.token, apiOrigin2);
|
|
15091
15956
|
}
|
|
15092
15957
|
const apiOrigin = this.apiOrigin;
|
|
15093
|
-
if (!
|
|
15958
|
+
if (!email2.includes("@") || !/^\d{6}$/.test(code))
|
|
15094
15959
|
throw new Error("Fresh email and six-digit verification code are required to manage this account");
|
|
15095
|
-
const login = await this.verifyCode(
|
|
15960
|
+
const login = await this.verifyCode(email2, code);
|
|
15096
15961
|
if (!login || typeof login.token !== "string" || !login.token)
|
|
15097
15962
|
throw new Error("The server did not return an authorized account session");
|
|
15098
15963
|
return new RemoteSkillsClient(login.token, apiOrigin);
|
|
15099
15964
|
}
|
|
15100
|
-
async listAccountWorkspaces(
|
|
15101
|
-
const login = await this.workspaceLogin(
|
|
15965
|
+
async listAccountWorkspaces(email2, code, expectedUserId) {
|
|
15966
|
+
const login = await this.workspaceLogin(email2, code, expectedUserId);
|
|
15102
15967
|
const result = await new RemoteSkillsClient(login.token, login.apiOrigin).listAccountWorkspaces(login.userId);
|
|
15103
15968
|
return { userId: login.userId, ...result };
|
|
15104
15969
|
}
|
|
15105
|
-
async switchWorkspace(
|
|
15970
|
+
async switchWorkspace(email2, code, context) {
|
|
15106
15971
|
const target = workspaceContext(context);
|
|
15107
|
-
const login = await this.workspaceLogin(
|
|
15972
|
+
const login = await this.workspaceLogin(email2, code, target.userId);
|
|
15108
15973
|
return new RemoteSkillsClient(login.token, login.apiOrigin).switchWorkspace(target);
|
|
15109
15974
|
}
|
|
15110
|
-
async workspaceLogin(
|
|
15975
|
+
async workspaceLogin(email2, code, expectedUserId) {
|
|
15111
15976
|
const expected = expectedUserId === undefined ? undefined : workspaceExpectedUserId(expectedUserId);
|
|
15112
15977
|
const apiOrigin = this.apiOrigin;
|
|
15113
|
-
if (typeof
|
|
15978
|
+
if (typeof email2 !== "string" || !email2.includes("@") || typeof code !== "string" || !/^\d{6}$/.test(code))
|
|
15114
15979
|
throw new Error("Fresh email and six-digit verification code are required to manage this account");
|
|
15115
15980
|
let response;
|
|
15116
15981
|
try {
|
|
@@ -15120,7 +15985,7 @@ class RemoteSkillsAuthClient {
|
|
|
15120
15985
|
credentials: "omit",
|
|
15121
15986
|
signal: AbortSignal.timeout(15000),
|
|
15122
15987
|
headers: { "Content-Type": "application/json" },
|
|
15123
|
-
body: JSON.stringify({ email, code })
|
|
15988
|
+
body: JSON.stringify({ email: email2, code })
|
|
15124
15989
|
});
|
|
15125
15990
|
} catch {
|
|
15126
15991
|
throw new HostedApiError("Unable to verify the Skills account.");
|
|
@@ -15137,40 +16002,67 @@ class RemoteSkillsAuthClient {
|
|
|
15137
16002
|
}
|
|
15138
16003
|
return { ...parseWorkspaceLogin(value, expected), apiOrigin };
|
|
15139
16004
|
}
|
|
15140
|
-
async
|
|
16005
|
+
async listWorkspaceInvitations(email2, code, context, options = {}) {
|
|
16006
|
+
const target = workspaceContext(context), captured = invitationInput("list", options);
|
|
16007
|
+
return (await this.sessionClient(email2, code, target)).listWorkspaceInvitations(target, captured);
|
|
16008
|
+
}
|
|
16009
|
+
async getWorkspaceInvitation(email2, code, context, invitationId) {
|
|
16010
|
+
const target = workspaceContext(context), captured = invitationInput("get", { invitationId });
|
|
16011
|
+
return (await this.sessionClient(email2, code, target)).getWorkspaceInvitation(target, captured.invitationId);
|
|
16012
|
+
}
|
|
16013
|
+
async issueWorkspaceInvitation(email2, code, context, input) {
|
|
16014
|
+
const target = workspaceContext(context), captured = invitationInput("issue", input);
|
|
16015
|
+
return (await this.sessionClient(email2, code, target)).issueWorkspaceInvitation(target, captured);
|
|
16016
|
+
}
|
|
16017
|
+
async resendWorkspaceInvitation(email2, code, context, invitationId, input) {
|
|
16018
|
+
const target = workspaceContext(context), captured = invitationInput("resend", { ...input, invitationId });
|
|
16019
|
+
const { invitationId: id, ...options } = captured;
|
|
16020
|
+
return (await this.sessionClient(email2, code, target)).resendWorkspaceInvitation(target, id, options);
|
|
16021
|
+
}
|
|
16022
|
+
async revokeWorkspaceInvitation(email2, code, context, invitationId, input) {
|
|
16023
|
+
const target = workspaceContext(context), captured = invitationInput("revoke", { ...input, invitationId });
|
|
16024
|
+
const { invitationId: id, ...options } = captured;
|
|
16025
|
+
return (await this.sessionClient(email2, code, target)).revokeWorkspaceInvitation(target, id, options);
|
|
16026
|
+
}
|
|
16027
|
+
async acceptWorkspaceInvitation(email2, code, context, invitationId, input) {
|
|
16028
|
+
const target = workspaceContext(context), captured = invitationInput("accept", { ...input, invitationId });
|
|
16029
|
+
const { invitationId: id, ...options } = captured;
|
|
16030
|
+
return (await this.sessionClient(email2, code, target)).acceptWorkspaceInvitation(target, id, options);
|
|
16031
|
+
}
|
|
16032
|
+
async createApiKey(email2, code, name, scopes, context) {
|
|
15141
16033
|
const capturedScopes = scopes === undefined ? undefined : [...scopes];
|
|
15142
|
-
return (await this.sessionClient(
|
|
16034
|
+
return (await this.sessionClient(email2, code, context)).createApiKey(name, capturedScopes);
|
|
15143
16035
|
}
|
|
15144
|
-
async listApiKeys(
|
|
15145
|
-
return (await this.sessionClient(
|
|
16036
|
+
async listApiKeys(email2, code, context) {
|
|
16037
|
+
return (await this.sessionClient(email2, code, context)).listApiKeys();
|
|
15146
16038
|
}
|
|
15147
|
-
async revokeApiKey(
|
|
15148
|
-
return (await this.sessionClient(
|
|
16039
|
+
async revokeApiKey(email2, code, keyId, context) {
|
|
16040
|
+
return (await this.sessionClient(email2, code, context)).revokeApiKey(keyId);
|
|
15149
16041
|
}
|
|
15150
|
-
async updateProfile(
|
|
16042
|
+
async updateProfile(email2, code, input, context) {
|
|
15151
16043
|
const body = customerNamePatch(input, "displayName");
|
|
15152
|
-
return (await this.sessionClient(
|
|
16044
|
+
return (await this.sessionClient(email2, code, context)).updateProfile({ displayName: body.displayName });
|
|
15153
16045
|
}
|
|
15154
|
-
async updateCurrentWorkspace(
|
|
16046
|
+
async updateCurrentWorkspace(email2, code, input, context) {
|
|
15155
16047
|
const body = customerNamePatch(input, "name");
|
|
15156
|
-
return (await this.sessionClient(
|
|
16048
|
+
return (await this.sessionClient(email2, code, context)).updateCurrentWorkspace({ name: body.name });
|
|
15157
16049
|
}
|
|
15158
|
-
async listWorkspaceMembers(
|
|
16050
|
+
async listWorkspaceMembers(email2, code, options = {}, context) {
|
|
15159
16051
|
workspaceMembersQuery(options);
|
|
15160
16052
|
const captured = { ...options };
|
|
15161
|
-
return (await this.sessionClient(
|
|
16053
|
+
return (await this.sessionClient(email2, code, context)).listWorkspaceMembers(captured);
|
|
15162
16054
|
}
|
|
15163
|
-
async setWorkspaceMemberRole(
|
|
16055
|
+
async setWorkspaceMemberRole(email2, code, membershipId, input, context) {
|
|
15164
16056
|
const captured = workspaceMemberRoleInput(membershipId, input);
|
|
15165
|
-
return (await this.sessionClient(
|
|
16057
|
+
return (await this.sessionClient(email2, code, context)).setWorkspaceMemberRole(captured.membershipId, captured.body);
|
|
15166
16058
|
}
|
|
15167
|
-
async leaveWorkspace(
|
|
16059
|
+
async leaveWorkspace(email2, code, context, input) {
|
|
15168
16060
|
const captured = workspaceLeaveInput(context, input);
|
|
15169
|
-
return (await this.sessionClient(
|
|
16061
|
+
return (await this.sessionClient(email2, code, captured.context)).leaveWorkspace(captured.context, captured.input);
|
|
15170
16062
|
}
|
|
15171
|
-
async removeWorkspaceMember(
|
|
16063
|
+
async removeWorkspaceMember(email2, code, membershipId, input, context) {
|
|
15172
16064
|
const captured = workspaceMemberRemovalInput(membershipId, input);
|
|
15173
|
-
return (await this.sessionClient(
|
|
16065
|
+
return (await this.sessionClient(email2, code, context)).removeWorkspaceMember(captured.membershipId, captured.body);
|
|
15174
16066
|
}
|
|
15175
16067
|
request(path, options) {
|
|
15176
16068
|
if (!["/api/auth/login", "/api/auth/verify", "/api/auth/device/start", "/api/auth/device/token", "/api/auth/keys", "/api/auth/whoami"].includes(path))
|
|
@@ -15179,244 +16071,257 @@ class RemoteSkillsAuthClient {
|
|
|
15179
16071
|
}
|
|
15180
16072
|
}
|
|
15181
16073
|
export {
|
|
15182
|
-
|
|
15183
|
-
writeStationHydration,
|
|
15184
|
-
writeRunLogs,
|
|
15185
|
-
writeRegistrySyncArtifact,
|
|
15186
|
-
writeManagedSkillDir,
|
|
15187
|
-
writeManagedAgentSkill,
|
|
15188
|
-
writeCorpusSkill,
|
|
15189
|
-
walkEntries,
|
|
15190
|
-
verifyContentHash,
|
|
15191
|
-
validateToolPrimitiveCoverage,
|
|
15192
|
-
validateStationId,
|
|
15193
|
-
validateSkillsCliMcpParity,
|
|
15194
|
-
validateSkillDirectory,
|
|
15195
|
-
validateRegistryConsistency,
|
|
15196
|
-
validatePortableSkillDirectory,
|
|
15197
|
-
validatePortableManifestContract,
|
|
15198
|
-
validateCron,
|
|
15199
|
-
validateBlogArticleRunOptions,
|
|
15200
|
-
uploadSkillsSnapshotFilesToS3,
|
|
15201
|
-
updateSkillRun,
|
|
15202
|
-
unsetConfig,
|
|
15203
|
-
unpinSkill,
|
|
15204
|
-
unpinProjectSkill,
|
|
15205
|
-
syncSkillsToAgents,
|
|
15206
|
-
summarizeMcpToolContract,
|
|
15207
|
-
storageCapabilities,
|
|
15208
|
-
skillsPostgresSyncSchemaSql,
|
|
15209
|
-
skillsCredentialOrReason,
|
|
15210
|
-
skillsCredentialFiles,
|
|
15211
|
-
skillsCredentialFilePath,
|
|
15212
|
-
skillExists,
|
|
15213
|
-
signSkillsAwsV4Request,
|
|
15214
|
-
sha256File,
|
|
15215
|
-
setSkillDisabled,
|
|
15216
|
-
setScheduleEnabled,
|
|
15217
|
-
selectsSkillsLocalMode,
|
|
15218
|
-
searchSkills,
|
|
15219
|
-
scaffoldPortableSkill,
|
|
15220
|
-
saveProjectConfig,
|
|
15221
|
-
saveFeedback,
|
|
15222
|
-
saveConfig,
|
|
15223
|
-
sanitizePublicDiscoveryText,
|
|
15224
|
-
runSkill,
|
|
15225
|
-
runPortableSkill,
|
|
15226
|
-
resolveSyncAgents,
|
|
15227
|
-
resolveStorageConfig,
|
|
15228
|
-
resolveSkillsNativeStorageConfig,
|
|
15229
|
-
resolveSkillsFleet,
|
|
15230
|
-
resolveSkillsApiOrigin,
|
|
15231
|
-
resolveSkillsApiKey,
|
|
15232
|
-
resolveSkillAlias,
|
|
15233
|
-
requireSkillsFleet,
|
|
15234
|
-
requireSkillsApiOrigin,
|
|
15235
|
-
requireSkillsApiKey,
|
|
15236
|
-
removeSkillForAgent,
|
|
15237
|
-
removeSkill,
|
|
15238
|
-
removeSchedule,
|
|
15239
|
-
removeManagedAgentSkill,
|
|
15240
|
-
recordScheduleRun,
|
|
15241
|
-
readPortableSkillManifest,
|
|
15242
|
-
pullSkills,
|
|
15243
|
-
publicDiscoveryEnvVars,
|
|
15244
|
-
publicDiscoveryDocumentation,
|
|
15245
|
-
publicDiscoveryDependencies,
|
|
15246
|
-
portPortableSkillDirectory,
|
|
15247
|
-
portPortableSkill,
|
|
15248
|
-
pointerSkillMd,
|
|
15249
|
-
planStationSnapshot,
|
|
15250
|
-
planStationHydration,
|
|
15251
|
-
planSkillsS3SnapshotUpload,
|
|
15252
|
-
pinSkill,
|
|
15253
|
-
pinProjectSkill,
|
|
15254
|
-
parseSkillFrontmatter,
|
|
15255
|
-
parseRemoteSkillPayload,
|
|
15256
|
-
parseRemoteRegistryPayload,
|
|
15257
|
-
noticeLocalSkillsMode,
|
|
15258
|
-
normalizeSkillsApiOrigin,
|
|
15259
|
-
normalizeSkillSlug,
|
|
15260
|
-
normalizeRemoteSkillRunContract,
|
|
15261
|
-
normalizePortableSkillName,
|
|
15262
|
-
normalizeLineEndings,
|
|
15263
|
-
loadRemoteSkill,
|
|
15264
|
-
loadRemoteRegistry,
|
|
15265
|
-
loadRegistryProfile,
|
|
15266
|
-
loadRegistry,
|
|
15267
|
-
loadProjectConfig,
|
|
15268
|
-
loadConfig,
|
|
15269
|
-
loadBasicRegistry,
|
|
15270
|
-
listToolPrimitives,
|
|
15271
|
-
listSkillRuns,
|
|
15272
|
-
listSchedules,
|
|
15273
|
-
listPortableSkills,
|
|
15274
|
-
listPortableSkillMetas,
|
|
15275
|
-
listPinnedSkills,
|
|
15276
|
-
listMcpToolContracts,
|
|
15277
|
-
isSyncAgent,
|
|
15278
|
-
isSkillsLocalOptIn,
|
|
15279
|
-
isRegularFile,
|
|
15280
|
-
isPortableWithinSkill,
|
|
15281
|
-
isGatewayBackedSkill,
|
|
15282
|
-
isExcludedSkillFileName,
|
|
15283
|
-
isBasicSkillName,
|
|
15284
|
-
installSkills,
|
|
15285
|
-
installSkillSource,
|
|
15286
|
-
installSkillManifest,
|
|
15287
|
-
installSkillForAgent,
|
|
15288
|
-
installSkill,
|
|
15289
|
-
importSkillsLocalSnapshot,
|
|
15290
|
-
homePathFor,
|
|
15291
|
-
getToolPrimitive,
|
|
15292
|
-
getStorageStatus,
|
|
15293
|
-
getStorageDatabaseUrl,
|
|
15294
|
-
getStorageDatabaseEnv,
|
|
15295
|
-
getSkillsStorageStatus,
|
|
15296
|
-
getSkillsStorageDatabaseUrl,
|
|
15297
|
-
getSkillsStorageDatabaseEnv,
|
|
15298
|
-
getSkillsNativeStorageStatus,
|
|
15299
|
-
getSkillsByTag,
|
|
15300
|
-
getSkillsByCategory,
|
|
15301
|
-
getSkillToolDependencies,
|
|
15302
|
-
getSkillRequirements,
|
|
15303
|
-
getSkillPath,
|
|
15304
|
-
getSkillDocs,
|
|
15305
|
-
getSkillBestDoc,
|
|
15306
|
-
getSkill,
|
|
15307
|
-
getRunExportDir,
|
|
15308
|
-
getPublicSkillDiscovery,
|
|
15309
|
-
getProjectStateDir,
|
|
15310
|
-
getProjectConfigPath,
|
|
15311
|
-
getPortableSkillsRoot,
|
|
15312
|
-
getPortableSkillPath,
|
|
15313
|
-
getPinnedSkills,
|
|
15314
|
-
getNextRun,
|
|
15315
|
-
getMcpToolDescriptions,
|
|
15316
|
-
getMcpResourceContracts,
|
|
15317
|
-
getInstalledSkills,
|
|
15318
|
-
getInstallMeta,
|
|
15319
|
-
getFeedbackDbPath,
|
|
15320
|
-
getDueSchedules,
|
|
15321
|
-
getDisabledSkills,
|
|
15322
|
-
getDisabledProjectSkills,
|
|
15323
|
-
getConfiguredApiUrl,
|
|
15324
|
-
getConfigPath,
|
|
15325
|
-
getCompactSkillDiscovery,
|
|
15326
|
-
getAllTags,
|
|
15327
|
-
getAgentSkillsDir,
|
|
15328
|
-
getAgentSkillPath,
|
|
15329
|
-
generateSkillMd,
|
|
15330
|
-
generateEnvExample,
|
|
15331
|
-
findSkillsParityForMcpTool,
|
|
15332
|
-
findSkillsParityForCliCommand,
|
|
15333
|
-
findSkillRun,
|
|
15334
|
-
findSimilarSkills,
|
|
15335
|
-
findPortableSkill,
|
|
15336
|
-
exportSkillsLocalSnapshot,
|
|
15337
|
-
ensureProjectConfig,
|
|
15338
|
-
enableSkill,
|
|
15339
|
-
disableSkill,
|
|
15340
|
-
destinationFor,
|
|
15341
|
-
describeMcpToolContracts,
|
|
15342
|
-
createSkillsSnapshotSyncRecord,
|
|
15343
|
-
createSkillsS3ObjectStore,
|
|
15344
|
-
createSkillsPostgresSyncStore,
|
|
15345
|
-
createSkillToolDependencies,
|
|
15346
|
-
createSkillRun,
|
|
15347
|
-
createSkillMcpMetadata,
|
|
15348
|
-
createRemoteSkillsClient,
|
|
15349
|
-
createRegistrySyncArtifact,
|
|
15350
|
-
createMcpContractManifest,
|
|
15351
|
-
createLocalSkillManifest,
|
|
15352
|
-
configuredSkillsApiUrl,
|
|
15353
|
-
computeContentHash,
|
|
15354
|
-
completeSkillRun,
|
|
15355
|
-
clearRegistryCache,
|
|
15356
|
-
canonicalizeManifest,
|
|
15357
|
-
buildSkillsS3ObjectUrl,
|
|
15358
|
-
buildSkillsApiUrl,
|
|
15359
|
-
appendRunEvent,
|
|
15360
|
-
agentGlobalSkillsDir,
|
|
15361
|
-
addSchedule,
|
|
15362
|
-
adaptSkillMdForAgent,
|
|
15363
|
-
WorkspaceLeaveInputError,
|
|
15364
|
-
WorkspaceIdentityMismatchError,
|
|
15365
|
-
WorkspaceContextInputError,
|
|
15366
|
-
TOOL_PRIMITIVE_SCHEMA_VERSION,
|
|
15367
|
-
TOOL_PRIMITIVES,
|
|
15368
|
-
StationSnapshotError,
|
|
15369
|
-
SkillsS3ObjectStore,
|
|
15370
|
-
SkillsPostgresSyncStore,
|
|
15371
|
-
SkillsFleetCredentialError,
|
|
15372
|
-
SYNC_MARKER_MANAGED_BY,
|
|
15373
|
-
SYNC_MARKER_FILE,
|
|
15374
|
-
SYNC_HOMES,
|
|
15375
|
-
SYNC_AGENTS,
|
|
15376
|
-
STORAGE_TABLES,
|
|
15377
|
-
STATION_SYNC_MANIFEST_SCHEMA,
|
|
15378
|
-
STATION_HYDRATION_MANIFEST_SCHEMA,
|
|
15379
|
-
SKILL_SYSTEM_DEPS_ALLOWLIST,
|
|
15380
|
-
SKILL_SANDBOX_MODES,
|
|
15381
|
-
SKILL_RUNTIMES,
|
|
15382
|
-
SKILL_ALIASES,
|
|
15383
|
-
SKILLS_STORAGE_TABLES,
|
|
15384
|
-
SKILLS_STORAGE_FALLBACK_ENV,
|
|
15385
|
-
SKILLS_STORAGE_ENV,
|
|
15386
|
-
SKILLS_PROJECT_DIR,
|
|
15387
|
-
SKILLS_NATIVE_STORAGE_FALLBACK_ENV,
|
|
15388
|
-
SKILLS_NATIVE_STORAGE_ENV,
|
|
15389
|
-
SKILLS_LOCAL_OPT_IN_ENV_KEYS,
|
|
15390
|
-
SKILLS_CLI_MCP_PARITY,
|
|
15391
|
-
SKILLS_APP,
|
|
15392
|
-
SKILLS_API_URL_ENV_KEYS,
|
|
15393
|
-
SKILLS_API_URL_ENV,
|
|
15394
|
-
SKILLS_API_KEY_ENV_KEYS,
|
|
15395
|
-
SKILLS_API_KEY_ENV,
|
|
15396
|
-
SKILLS,
|
|
15397
|
-
RemoteWorkspaceSelectionError,
|
|
15398
|
-
RemoteWorkspaceMemberError,
|
|
15399
|
-
RemoteWorkspaceLeaveUnconfirmedError,
|
|
15400
|
-
RemoteWorkspaceLeaveError,
|
|
15401
|
-
RemoteSkillsClient,
|
|
15402
|
-
RemoteSkillsAuthClient,
|
|
15403
|
-
RemoteRouteUnsupportedError,
|
|
15404
|
-
RemoteRequestError,
|
|
15405
|
-
RemoteCreditApprovalError,
|
|
15406
|
-
RemoteCapabilityUnavailableError,
|
|
15407
|
-
REMOTE_SKILL_RUN_CONTRACT_VERSION,
|
|
15408
|
-
REFUSED_SCANNER_FLAGGED,
|
|
15409
|
-
PullSkillError,
|
|
15410
|
-
PROJECT_CONFIG_FILE,
|
|
15411
|
-
PORTABLE_SKILL_STANDARD,
|
|
15412
|
-
PORTABLE_SKILL_SCHEMA,
|
|
15413
|
-
PORTABLE_SKILL_DEFAULT_VERSION,
|
|
15414
|
-
MissingSkillsFleetError,
|
|
15415
|
-
MCP_CONTRACT_SCHEMA_VERSION,
|
|
15416
|
-
HostedApiError,
|
|
15417
|
-
DEFAULT_EXPORT_DIR,
|
|
15418
|
-
CATEGORIES,
|
|
15419
|
-
BASIC_SKILL_NAMES,
|
|
16074
|
+
AGENT_TARGETS,
|
|
15420
16075
|
ARTICLE_GENERATION_SLUG,
|
|
15421
|
-
|
|
16076
|
+
BASIC_SKILL_NAMES,
|
|
16077
|
+
CATEGORIES,
|
|
16078
|
+
CONTENT_HASH_LIMITS,
|
|
16079
|
+
ContentHashInputError,
|
|
16080
|
+
DEFAULT_EXPORT_DIR,
|
|
16081
|
+
HostedApiError,
|
|
16082
|
+
InvitationEmailInputError,
|
|
16083
|
+
MCP_CONTRACT_SCHEMA_VERSION,
|
|
16084
|
+
MissingSkillsFleetError,
|
|
16085
|
+
PORTABLE_SKILL_DEFAULT_VERSION,
|
|
16086
|
+
PORTABLE_SKILL_SCHEMA,
|
|
16087
|
+
PORTABLE_SKILL_STANDARD,
|
|
16088
|
+
PROJECT_CONFIG_FILE,
|
|
16089
|
+
PullSkillError,
|
|
16090
|
+
REFUSED_SCANNER_FLAGGED,
|
|
16091
|
+
REMOTE_SKILL_RUN_CONTRACT_VERSION,
|
|
16092
|
+
RemoteCapabilityUnavailableError,
|
|
16093
|
+
RemoteCreditApprovalError,
|
|
16094
|
+
RemoteInvitationEmailError,
|
|
16095
|
+
RemoteInvitationEmailUnconfirmedError,
|
|
16096
|
+
RemoteQuoteUnavailableError,
|
|
16097
|
+
RemoteRequestError,
|
|
16098
|
+
RemoteRouteUnsupportedError,
|
|
16099
|
+
RemoteSkillsAuthClient,
|
|
16100
|
+
RemoteSkillsClient,
|
|
16101
|
+
RemoteWorkspaceInvitationError,
|
|
16102
|
+
RemoteWorkspaceInvitationReadError,
|
|
16103
|
+
RemoteWorkspaceInvitationUnconfirmedError,
|
|
16104
|
+
RemoteWorkspaceLeaveError,
|
|
16105
|
+
RemoteWorkspaceLeaveUnconfirmedError,
|
|
16106
|
+
RemoteWorkspaceMemberError,
|
|
16107
|
+
RemoteWorkspaceSelectionError,
|
|
16108
|
+
SKILLS,
|
|
16109
|
+
SKILLS_API_KEY_ENV,
|
|
16110
|
+
SKILLS_API_KEY_ENV_KEYS,
|
|
16111
|
+
SKILLS_API_URL_ENV,
|
|
16112
|
+
SKILLS_API_URL_ENV_KEYS,
|
|
16113
|
+
SKILLS_APP,
|
|
16114
|
+
SKILLS_CLI_MCP_PARITY,
|
|
16115
|
+
SKILLS_LOCAL_OPT_IN_ENV_KEYS,
|
|
16116
|
+
SKILLS_NATIVE_STORAGE_ENV,
|
|
16117
|
+
SKILLS_NATIVE_STORAGE_FALLBACK_ENV,
|
|
16118
|
+
SKILLS_PROJECT_DIR,
|
|
16119
|
+
SKILLS_STORAGE_ENV,
|
|
16120
|
+
SKILLS_STORAGE_FALLBACK_ENV,
|
|
16121
|
+
SKILLS_STORAGE_TABLES,
|
|
16122
|
+
SKILL_ALIASES,
|
|
16123
|
+
SKILL_RUNTIMES,
|
|
16124
|
+
SKILL_SANDBOX_MODES,
|
|
16125
|
+
SKILL_SYSTEM_DEPS_ALLOWLIST,
|
|
16126
|
+
STATION_HYDRATION_MANIFEST_SCHEMA,
|
|
16127
|
+
STATION_SYNC_MANIFEST_SCHEMA,
|
|
16128
|
+
STORAGE_TABLES,
|
|
16129
|
+
SYNC_AGENTS,
|
|
16130
|
+
SYNC_HOMES,
|
|
16131
|
+
SYNC_MARKER_FILE,
|
|
16132
|
+
SYNC_MARKER_MANAGED_BY,
|
|
16133
|
+
SkillsFleetCredentialError,
|
|
16134
|
+
SkillsPostgresSyncStore,
|
|
16135
|
+
SkillsS3ObjectStore,
|
|
16136
|
+
StationSnapshotError,
|
|
16137
|
+
TOOL_PRIMITIVES,
|
|
16138
|
+
TOOL_PRIMITIVE_SCHEMA_VERSION,
|
|
16139
|
+
WorkspaceContextInputError,
|
|
16140
|
+
WorkspaceIdentityMismatchError,
|
|
16141
|
+
WorkspaceInvitationInputError,
|
|
16142
|
+
WorkspaceLeaveInputError,
|
|
16143
|
+
adaptSkillMdForAgent,
|
|
16144
|
+
addSchedule,
|
|
16145
|
+
agentGlobalSkillsDir,
|
|
16146
|
+
appendRunEvent,
|
|
16147
|
+
buildSkillsApiUrl,
|
|
16148
|
+
buildSkillsS3ObjectUrl,
|
|
16149
|
+
canonicalizeManifest,
|
|
16150
|
+
clearRegistryCache,
|
|
16151
|
+
completeSkillRun,
|
|
16152
|
+
computeContentHash,
|
|
16153
|
+
computeContentHashFromEntries,
|
|
16154
|
+
configuredSkillsApiUrl,
|
|
16155
|
+
createLocalSkillManifest,
|
|
16156
|
+
createMcpContractManifest,
|
|
16157
|
+
createRegistrySyncArtifact,
|
|
16158
|
+
createRemoteSkillsClient,
|
|
16159
|
+
createSkillMcpMetadata,
|
|
16160
|
+
createSkillRun,
|
|
16161
|
+
createSkillToolDependencies,
|
|
16162
|
+
createSkillsPostgresSyncStore,
|
|
16163
|
+
createSkillsS3ObjectStore,
|
|
16164
|
+
createSkillsSnapshotSyncRecord,
|
|
16165
|
+
describeMcpToolContracts,
|
|
16166
|
+
destinationFor,
|
|
16167
|
+
disableSkill,
|
|
16168
|
+
enableSkill,
|
|
16169
|
+
ensureProjectConfig,
|
|
16170
|
+
exportSkillsLocalSnapshot,
|
|
16171
|
+
findPortableSkill,
|
|
16172
|
+
findSimilarSkills,
|
|
16173
|
+
findSkillRun,
|
|
16174
|
+
findSkillsParityForCliCommand,
|
|
16175
|
+
findSkillsParityForMcpTool,
|
|
16176
|
+
generateEnvExample,
|
|
16177
|
+
generateSkillMd,
|
|
16178
|
+
getAgentSkillPath,
|
|
16179
|
+
getAgentSkillsDir,
|
|
16180
|
+
getAllTags,
|
|
16181
|
+
getCompactSkillDiscovery,
|
|
16182
|
+
getConfigPath,
|
|
16183
|
+
getConfiguredApiUrl,
|
|
16184
|
+
getDisabledProjectSkills,
|
|
16185
|
+
getDisabledSkills,
|
|
16186
|
+
getDueSchedules,
|
|
16187
|
+
getFeedbackDbPath,
|
|
16188
|
+
getInstallMeta,
|
|
16189
|
+
getInstalledSkills,
|
|
16190
|
+
getMcpResourceContracts,
|
|
16191
|
+
getMcpToolDescriptions,
|
|
16192
|
+
getNextRun,
|
|
16193
|
+
getPinnedSkills,
|
|
16194
|
+
getPortableSkillPath,
|
|
16195
|
+
getPortableSkillsRoot,
|
|
16196
|
+
getProjectConfigPath,
|
|
16197
|
+
getProjectStateDir,
|
|
16198
|
+
getPublicSkillDiscovery,
|
|
16199
|
+
getRunExportDir,
|
|
16200
|
+
getSkill,
|
|
16201
|
+
getSkillBestDoc,
|
|
16202
|
+
getSkillDocs,
|
|
16203
|
+
getSkillPath,
|
|
16204
|
+
getSkillRequirements,
|
|
16205
|
+
getSkillToolDependencies,
|
|
16206
|
+
getSkillsByCategory,
|
|
16207
|
+
getSkillsByTag,
|
|
16208
|
+
getSkillsNativeStorageStatus,
|
|
16209
|
+
getSkillsStorageDatabaseEnv,
|
|
16210
|
+
getSkillsStorageDatabaseUrl,
|
|
16211
|
+
getSkillsStorageStatus,
|
|
16212
|
+
getStorageDatabaseEnv,
|
|
16213
|
+
getStorageDatabaseUrl,
|
|
16214
|
+
getStorageStatus,
|
|
16215
|
+
getToolPrimitive,
|
|
16216
|
+
homePathFor,
|
|
16217
|
+
importSkillsLocalSnapshot,
|
|
16218
|
+
installSkill,
|
|
16219
|
+
installSkillForAgent,
|
|
16220
|
+
installSkillManifest,
|
|
16221
|
+
installSkillSource,
|
|
16222
|
+
installSkills,
|
|
16223
|
+
isBasicSkillName,
|
|
16224
|
+
isExcludedSkillFileName,
|
|
16225
|
+
isGatewayBackedSkill,
|
|
16226
|
+
isPortableWithinSkill,
|
|
16227
|
+
isRegularFile,
|
|
16228
|
+
isSkillsLocalOptIn,
|
|
16229
|
+
isSyncAgent,
|
|
16230
|
+
listMcpToolContracts,
|
|
16231
|
+
listPinnedSkills,
|
|
16232
|
+
listPortableSkillMetas,
|
|
16233
|
+
listPortableSkills,
|
|
16234
|
+
listSchedules,
|
|
16235
|
+
listSkillRuns,
|
|
16236
|
+
listToolPrimitives,
|
|
16237
|
+
loadBasicRegistry,
|
|
16238
|
+
loadConfig,
|
|
16239
|
+
loadProjectConfig,
|
|
16240
|
+
loadRegistry,
|
|
16241
|
+
loadRegistryProfile,
|
|
16242
|
+
loadRemoteRegistry,
|
|
16243
|
+
loadRemoteSkill,
|
|
16244
|
+
normalizeLineEndings,
|
|
16245
|
+
normalizePortableSkillName,
|
|
16246
|
+
normalizeRemoteSkillRunContract,
|
|
16247
|
+
normalizeSkillSlug,
|
|
16248
|
+
normalizeSkillsApiOrigin,
|
|
16249
|
+
noticeLocalSkillsMode,
|
|
16250
|
+
parseRemoteRegistryPayload,
|
|
16251
|
+
parseRemoteSkillPayload,
|
|
16252
|
+
parseSkillFrontmatter,
|
|
16253
|
+
pinProjectSkill,
|
|
16254
|
+
pinSkill,
|
|
16255
|
+
planSkillsS3SnapshotUpload,
|
|
16256
|
+
planStationHydration,
|
|
16257
|
+
planStationSnapshot,
|
|
16258
|
+
pointerSkillMd,
|
|
16259
|
+
portPortableSkill,
|
|
16260
|
+
portPortableSkillDirectory,
|
|
16261
|
+
publicDiscoveryDependencies,
|
|
16262
|
+
publicDiscoveryDocumentation,
|
|
16263
|
+
publicDiscoveryEnvVars,
|
|
16264
|
+
pullSkills,
|
|
16265
|
+
readPortableSkillManifest,
|
|
16266
|
+
recordScheduleRun,
|
|
16267
|
+
removeManagedAgentSkill,
|
|
16268
|
+
removeSchedule,
|
|
16269
|
+
removeSkill,
|
|
16270
|
+
removeSkillForAgent,
|
|
16271
|
+
requireSkillsApiKey,
|
|
16272
|
+
requireSkillsApiOrigin,
|
|
16273
|
+
requireSkillsFleet,
|
|
16274
|
+
resolveSkillAlias,
|
|
16275
|
+
resolveSkillsApiKey,
|
|
16276
|
+
resolveSkillsApiOrigin,
|
|
16277
|
+
resolveSkillsFleet,
|
|
16278
|
+
resolveSkillsNativeStorageConfig,
|
|
16279
|
+
resolveStorageConfig,
|
|
16280
|
+
resolveSyncAgents,
|
|
16281
|
+
revisionIdOf,
|
|
16282
|
+
runPortableSkill,
|
|
16283
|
+
runSkill,
|
|
16284
|
+
sanitizePublicDiscoveryText,
|
|
16285
|
+
saveConfig,
|
|
16286
|
+
saveFeedback,
|
|
16287
|
+
saveProjectConfig,
|
|
16288
|
+
scaffoldPortableSkill,
|
|
16289
|
+
searchSkills,
|
|
16290
|
+
selectsSkillsLocalMode,
|
|
16291
|
+
setScheduleEnabled,
|
|
16292
|
+
setSkillDisabled,
|
|
16293
|
+
sha256File,
|
|
16294
|
+
signSkillsAwsV4Request,
|
|
16295
|
+
skillExists,
|
|
16296
|
+
skillsCredentialFilePath,
|
|
16297
|
+
skillsCredentialFiles,
|
|
16298
|
+
skillsCredentialOrReason,
|
|
16299
|
+
skillsPostgresSyncSchemaSql,
|
|
16300
|
+
storageCapabilities,
|
|
16301
|
+
summarizeMcpToolContract,
|
|
16302
|
+
syncSkillsToAgents,
|
|
16303
|
+
unpinProjectSkill,
|
|
16304
|
+
unpinSkill,
|
|
16305
|
+
unsetConfig,
|
|
16306
|
+
updateSkillRun,
|
|
16307
|
+
uploadSkillsSnapshotFilesToS3,
|
|
16308
|
+
validateBlogArticleRunOptions,
|
|
16309
|
+
validateCron,
|
|
16310
|
+
validatePortableManifestContract,
|
|
16311
|
+
validatePortableSkillDirectory,
|
|
16312
|
+
validateRegistryConsistency,
|
|
16313
|
+
validateSkillDirectory,
|
|
16314
|
+
validateSkillsCliMcpParity,
|
|
16315
|
+
validateStationId,
|
|
16316
|
+
validateToolPrimitiveCoverage,
|
|
16317
|
+
verifyContentHash,
|
|
16318
|
+
verifyContentHashFromEntries,
|
|
16319
|
+
walkEntries,
|
|
16320
|
+
writeCorpusSkill,
|
|
16321
|
+
writeManagedAgentSkill,
|
|
16322
|
+
writeManagedSkillDir,
|
|
16323
|
+
writeRegistrySyncArtifact,
|
|
16324
|
+
writeRunLogs,
|
|
16325
|
+
writeStationHydration,
|
|
16326
|
+
writeStationSnapshot
|
|
15422
16327
|
};
|