artifact-cafe 0.0.7 → 0.0.8
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.js +378 -13
- package/package.json +9 -9
package/dist/index.js
CHANGED
|
@@ -112,8 +112,9 @@ var anchorSchema = z2.discriminatedUnion("type", [
|
|
|
112
112
|
pointAnchorSchema,
|
|
113
113
|
textAnchorSchema
|
|
114
114
|
]);
|
|
115
|
+
var displayNameSchema = z2.string().trim().min(1).max(64);
|
|
115
116
|
var guestSchema = z2.object({
|
|
116
|
-
displayName:
|
|
117
|
+
displayName: displayNameSchema,
|
|
117
118
|
guestId: z2.string().min(16)
|
|
118
119
|
});
|
|
119
120
|
var createCommentThreadSchema = z2.object({
|
|
@@ -207,8 +208,10 @@ var ownArtifactSchema = z4.object({
|
|
|
207
208
|
// Owned artifacts normally never expire; non-null only while an
|
|
208
209
|
// expiry is still set (e.g. an unclaimed publish surfaced here later).
|
|
209
210
|
expiresAt: z4.string().nullable(),
|
|
210
|
-
// SPEC-2 §8.4 — the containing folder
|
|
211
|
-
//
|
|
211
|
+
// SPEC-2 §8.4 — the containing folder for workspace-owned artifacts;
|
|
212
|
+
// both null for personal artifacts. `folderId` drives the dashboard's
|
|
213
|
+
// move control and folder filter; `folderName` is the display label.
|
|
214
|
+
folderId: z4.string().nullable(),
|
|
212
215
|
folderName: z4.string().nullable(),
|
|
213
216
|
// Whether a publish token is still active — revocable from the
|
|
214
217
|
// dashboard (§6.18); the token itself is never returned.
|
|
@@ -655,7 +658,7 @@ function createApiClient(apiUrl2, publishToken) {
|
|
|
655
658
|
});
|
|
656
659
|
return request(
|
|
657
660
|
`${base}/api/v1/artifacts/${artifactId}/comments/export?${params}`,
|
|
658
|
-
{ method: "GET" },
|
|
661
|
+
{ headers, method: "GET" },
|
|
659
662
|
(d) => commentExportSchema.parse(d)
|
|
660
663
|
);
|
|
661
664
|
},
|
|
@@ -669,7 +672,7 @@ function createApiClient(apiUrl2, publishToken) {
|
|
|
669
672
|
async getArtifact(artifactId) {
|
|
670
673
|
return request(
|
|
671
674
|
`${base}/api/v1/artifacts/${artifactId}`,
|
|
672
|
-
{ method: "GET" },
|
|
675
|
+
{ headers, method: "GET" },
|
|
673
676
|
(d) => artifactResponseSchema.parse(d)
|
|
674
677
|
);
|
|
675
678
|
},
|
|
@@ -705,6 +708,34 @@ function createApiClient(apiUrl2, publishToken) {
|
|
|
705
708
|
(d) => meResponseSchema.parse(d)
|
|
706
709
|
);
|
|
707
710
|
},
|
|
711
|
+
// SPEC §6.7 — reopen a resolved thread. Same auth as resolve.
|
|
712
|
+
async reopenThread(threadId) {
|
|
713
|
+
return request(
|
|
714
|
+
`${base}/api/v1/comment-threads/${threadId}/reopen`,
|
|
715
|
+
{ body: "{}", headers, method: "POST" },
|
|
716
|
+
(d) => commentThreadSchema.parse(d)
|
|
717
|
+
);
|
|
718
|
+
},
|
|
719
|
+
// SPEC §6.5 — post a reply into a thread. Authorized by this client's
|
|
720
|
+
// credential: the artifact's publish token (the reply renders as the
|
|
721
|
+
// agent) or the owner's account key (renders as the owner). No guest
|
|
722
|
+
// payload — the credential is the identity.
|
|
723
|
+
async replyThread(threadId, body) {
|
|
724
|
+
return request(
|
|
725
|
+
`${base}/api/v1/comment-threads/${threadId}/messages`,
|
|
726
|
+
{ body: JSON.stringify({ body }), headers, method: "POST" },
|
|
727
|
+
(d) => commentThreadSchema.parse(d)
|
|
728
|
+
);
|
|
729
|
+
},
|
|
730
|
+
// SPEC §6.6 — mark a thread resolved. Authorized by this client's
|
|
731
|
+
// credential: the artifact's publish token, or the owner's account key.
|
|
732
|
+
async resolveThread(threadId) {
|
|
733
|
+
return request(
|
|
734
|
+
`${base}/api/v1/comment-threads/${threadId}/resolve`,
|
|
735
|
+
{ body: "{}", headers, method: "POST" },
|
|
736
|
+
(d) => commentThreadSchema.parse(d)
|
|
737
|
+
);
|
|
738
|
+
},
|
|
708
739
|
// SPEC §6.16 — set a password (string) or clear it (null). Authorized
|
|
709
740
|
// by the publish token this client was created with.
|
|
710
741
|
async setProtection(artifactId, password) {
|
|
@@ -1067,8 +1098,8 @@ function printThread(t) {
|
|
|
1067
1098
|
console.log(` \u21B3 at ${t.anchor.elementPath}`);
|
|
1068
1099
|
}
|
|
1069
1100
|
console.log(indent(t.body, " "));
|
|
1070
|
-
for (const
|
|
1071
|
-
console.log(indent(`${
|
|
1101
|
+
for (const reply2 of t.replies) {
|
|
1102
|
+
console.log(indent(`${reply2.author}: ${reply2.body}`, " "));
|
|
1072
1103
|
}
|
|
1073
1104
|
console.log("");
|
|
1074
1105
|
}
|
|
@@ -1486,6 +1517,11 @@ function printCliError(err, json) {
|
|
|
1486
1517
|
if (err.retryAfter) {
|
|
1487
1518
|
console.error(` Retry in ${err.retryAfter}s.`);
|
|
1488
1519
|
}
|
|
1520
|
+
if (err.code === "password_required") {
|
|
1521
|
+
console.error(
|
|
1522
|
+
" Run `artifact-cafe login` as the owner, or run from the published folder (its publish token unlocks it)."
|
|
1523
|
+
);
|
|
1524
|
+
}
|
|
1489
1525
|
}
|
|
1490
1526
|
return;
|
|
1491
1527
|
}
|
|
@@ -1625,7 +1661,7 @@ function pickArtifact(artifacts) {
|
|
|
1625
1661
|
);
|
|
1626
1662
|
});
|
|
1627
1663
|
const rl = createInterface({ input: process.stdin, output: process.stdout });
|
|
1628
|
-
return new Promise((
|
|
1664
|
+
return new Promise((resolve2, reject) => {
|
|
1629
1665
|
rl.question(`
|
|
1630
1666
|
Link which? [1-${artifacts.length}]: `, (answer) => {
|
|
1631
1667
|
rl.close();
|
|
@@ -1634,7 +1670,7 @@ Link which? [1-${artifacts.length}]: `, (answer) => {
|
|
|
1634
1670
|
reject(new Error(`Enter a number between 1 and ${artifacts.length}.`));
|
|
1635
1671
|
return;
|
|
1636
1672
|
}
|
|
1637
|
-
|
|
1673
|
+
resolve2(artifacts[n - 1]);
|
|
1638
1674
|
});
|
|
1639
1675
|
});
|
|
1640
1676
|
}
|
|
@@ -1701,7 +1737,7 @@ function apiUrl() {
|
|
|
1701
1737
|
return (process.env.ARTIFACT_CAFE_URL ?? DEFAULT_API_URL).replace(/\/$/, "");
|
|
1702
1738
|
}
|
|
1703
1739
|
function promptSecret(question) {
|
|
1704
|
-
return new Promise((
|
|
1740
|
+
return new Promise((resolve2) => {
|
|
1705
1741
|
const rl = createInterface2({
|
|
1706
1742
|
input: process.stdin,
|
|
1707
1743
|
output: process.stdout
|
|
@@ -1716,7 +1752,7 @@ function promptSecret(question) {
|
|
|
1716
1752
|
rl.question(question, (answer) => {
|
|
1717
1753
|
rl.close();
|
|
1718
1754
|
process.stdout.write("\n");
|
|
1719
|
-
|
|
1755
|
+
resolve2(answer);
|
|
1720
1756
|
});
|
|
1721
1757
|
muted = true;
|
|
1722
1758
|
});
|
|
@@ -1871,6 +1907,234 @@ async function protect(opts) {
|
|
|
1871
1907
|
);
|
|
1872
1908
|
}
|
|
1873
1909
|
|
|
1910
|
+
// src/reply.ts
|
|
1911
|
+
import path10 from "path";
|
|
1912
|
+
async function readStdin() {
|
|
1913
|
+
if (process.stdin.isTTY) {
|
|
1914
|
+
return "";
|
|
1915
|
+
}
|
|
1916
|
+
const chunks = [];
|
|
1917
|
+
for await (const chunk of process.stdin) {
|
|
1918
|
+
chunks.push(chunk);
|
|
1919
|
+
}
|
|
1920
|
+
return Buffer.concat(chunks).toString("utf8");
|
|
1921
|
+
}
|
|
1922
|
+
async function replyToThread(opts) {
|
|
1923
|
+
const threadId = opts.thread?.trim();
|
|
1924
|
+
if (!threadId) {
|
|
1925
|
+
throw new Error(
|
|
1926
|
+
"Pass the thread id to reply to \u2014 get it from `artifact-cafe comments --json`."
|
|
1927
|
+
);
|
|
1928
|
+
}
|
|
1929
|
+
const body = (opts.body ?? await readStdin()).trim();
|
|
1930
|
+
if (!body) {
|
|
1931
|
+
throw new Error(
|
|
1932
|
+
'Nothing to post. Pass the reply with --body "\u2026", or pipe it on stdin.'
|
|
1933
|
+
);
|
|
1934
|
+
}
|
|
1935
|
+
const dir = path10.resolve(opts.dir);
|
|
1936
|
+
const target = resolveArtifactTarget(dir, {
|
|
1937
|
+
apiKey: opts.apiKey,
|
|
1938
|
+
artifact: opts.artifact
|
|
1939
|
+
});
|
|
1940
|
+
const client = createApiClient(target.apiUrl, target.credential);
|
|
1941
|
+
let thread = await client.replyThread(threadId, body);
|
|
1942
|
+
if (opts.resolve) {
|
|
1943
|
+
thread = await client.resolveThread(threadId);
|
|
1944
|
+
}
|
|
1945
|
+
if (opts.json) {
|
|
1946
|
+
console.log(
|
|
1947
|
+
JSON.stringify(
|
|
1948
|
+
{
|
|
1949
|
+
id: thread.id,
|
|
1950
|
+
messageCount: thread.messages.length,
|
|
1951
|
+
status: thread.status
|
|
1952
|
+
},
|
|
1953
|
+
null,
|
|
1954
|
+
2
|
|
1955
|
+
)
|
|
1956
|
+
);
|
|
1957
|
+
return;
|
|
1958
|
+
}
|
|
1959
|
+
const closed = opts.resolve ? " and resolved it" : "";
|
|
1960
|
+
console.log(`\u2713 Replied to ${thread.id}${closed} \u2014 now ${thread.status}.`);
|
|
1961
|
+
}
|
|
1962
|
+
|
|
1963
|
+
// src/resolve.ts
|
|
1964
|
+
import path11 from "path";
|
|
1965
|
+
async function changeThreadStatus(opts) {
|
|
1966
|
+
const threadId = opts.thread?.trim();
|
|
1967
|
+
if (!threadId) {
|
|
1968
|
+
throw new Error(
|
|
1969
|
+
`Pass the thread id to ${opts.action} \u2014 get it from \`artifact-cafe comments --json\`.`
|
|
1970
|
+
);
|
|
1971
|
+
}
|
|
1972
|
+
const dir = path11.resolve(opts.dir);
|
|
1973
|
+
const target = resolveArtifactTarget(dir, {
|
|
1974
|
+
apiKey: opts.apiKey,
|
|
1975
|
+
artifact: opts.artifact
|
|
1976
|
+
});
|
|
1977
|
+
const client = createApiClient(target.apiUrl, target.credential);
|
|
1978
|
+
const thread = opts.action === "resolve" ? await client.resolveThread(threadId) : await client.reopenThread(threadId);
|
|
1979
|
+
if (opts.json) {
|
|
1980
|
+
console.log(
|
|
1981
|
+
JSON.stringify({ id: thread.id, status: thread.status }, null, 2)
|
|
1982
|
+
);
|
|
1983
|
+
return;
|
|
1984
|
+
}
|
|
1985
|
+
const verb = opts.action === "resolve" ? "Resolved" : "Reopened";
|
|
1986
|
+
console.log(`\u2713 ${verb} ${thread.id} \u2014 now ${thread.status}.`);
|
|
1987
|
+
}
|
|
1988
|
+
|
|
1989
|
+
// src/update.ts
|
|
1990
|
+
import { existsSync as existsSync3, mkdirSync as mkdirSync3, readFileSync as readFileSync5, writeFileSync as writeFileSync3 } from "fs";
|
|
1991
|
+
import { createRequire } from "module";
|
|
1992
|
+
import { homedir as homedir2 } from "os";
|
|
1993
|
+
import path12 from "path";
|
|
1994
|
+
import { z as z15 } from "zod";
|
|
1995
|
+
var REGISTRY_LATEST_URL = "https://registry.npmjs.org/artifact-cafe/latest";
|
|
1996
|
+
var SKILL_SOURCE_URL = "https://raw.githubusercontent.com/Artifact-Cafe/skill/main/artifact-cafe/SKILL.md";
|
|
1997
|
+
var SKILL_UPDATE_COMMAND = "npx skills add artifact-cafe/skill --skill artifact-cafe -g";
|
|
1998
|
+
var CHECK_TTL_MS = 24 * 60 * 60 * 1e3;
|
|
1999
|
+
var FETCH_TIMEOUT_MS = 2e3;
|
|
2000
|
+
var SKILL_VERSION_PATTERN = /\*\*Skill version:\s*(\d+\.\d+\.\d+)\*\*/;
|
|
2001
|
+
var cacheSchema = z15.object({
|
|
2002
|
+
checkedAt: z15.number(),
|
|
2003
|
+
cliLatest: z15.string().nullable(),
|
|
2004
|
+
skillLatest: z15.string().nullable(),
|
|
2005
|
+
version: z15.literal(1)
|
|
2006
|
+
});
|
|
2007
|
+
function cliVersion() {
|
|
2008
|
+
const pkg = createRequire(import.meta.url)("../package.json");
|
|
2009
|
+
return pkg.version;
|
|
2010
|
+
}
|
|
2011
|
+
function cachePath() {
|
|
2012
|
+
return path12.join(homedir2(), ".artifactcafe", "update-check.json");
|
|
2013
|
+
}
|
|
2014
|
+
function readCache() {
|
|
2015
|
+
try {
|
|
2016
|
+
return cacheSchema.parse(JSON.parse(readFileSync5(cachePath(), "utf8")));
|
|
2017
|
+
} catch {
|
|
2018
|
+
return null;
|
|
2019
|
+
}
|
|
2020
|
+
}
|
|
2021
|
+
function writeCache(cache) {
|
|
2022
|
+
try {
|
|
2023
|
+
mkdirSync3(path12.dirname(cachePath()), { mode: 448, recursive: true });
|
|
2024
|
+
writeFileSync3(cachePath(), `${JSON.stringify(cache, null, 2)}
|
|
2025
|
+
`);
|
|
2026
|
+
} catch {
|
|
2027
|
+
}
|
|
2028
|
+
}
|
|
2029
|
+
function isNewerVersion(candidate, current) {
|
|
2030
|
+
const parse = (value) => value.split(".").map((part) => Number.parseInt(part, 10) || 0);
|
|
2031
|
+
const a = parse(candidate);
|
|
2032
|
+
const b = parse(current);
|
|
2033
|
+
for (let i = 0; i < 3; i++) {
|
|
2034
|
+
if ((a[i] ?? 0) !== (b[i] ?? 0)) {
|
|
2035
|
+
return (a[i] ?? 0) > (b[i] ?? 0);
|
|
2036
|
+
}
|
|
2037
|
+
}
|
|
2038
|
+
return false;
|
|
2039
|
+
}
|
|
2040
|
+
async function fetchJson(url) {
|
|
2041
|
+
const res = await fetch(url, {
|
|
2042
|
+
signal: AbortSignal.timeout(FETCH_TIMEOUT_MS)
|
|
2043
|
+
});
|
|
2044
|
+
if (!res.ok) {
|
|
2045
|
+
throw new Error(`GET ${url} \u2192 ${res.status}`);
|
|
2046
|
+
}
|
|
2047
|
+
return res.json();
|
|
2048
|
+
}
|
|
2049
|
+
async function fetchText(url) {
|
|
2050
|
+
const res = await fetch(url, {
|
|
2051
|
+
signal: AbortSignal.timeout(FETCH_TIMEOUT_MS)
|
|
2052
|
+
});
|
|
2053
|
+
if (!res.ok) {
|
|
2054
|
+
throw new Error(`GET ${url} \u2192 ${res.status}`);
|
|
2055
|
+
}
|
|
2056
|
+
return res.text();
|
|
2057
|
+
}
|
|
2058
|
+
async function fetchLatestVersions(previous) {
|
|
2059
|
+
const [cli, skill] = await Promise.all([
|
|
2060
|
+
fetchJson(REGISTRY_LATEST_URL).then((body) => z15.object({ version: z15.string() }).parse(body).version).catch(() => null),
|
|
2061
|
+
fetchText(SKILL_SOURCE_URL).then((body) => SKILL_VERSION_PATTERN.exec(body)?.[1] ?? null).catch(() => null)
|
|
2062
|
+
]);
|
|
2063
|
+
return {
|
|
2064
|
+
checkedAt: Date.now(),
|
|
2065
|
+
cliLatest: cli ?? previous?.cliLatest ?? null,
|
|
2066
|
+
skillLatest: skill ?? previous?.skillLatest ?? null,
|
|
2067
|
+
version: 1
|
|
2068
|
+
};
|
|
2069
|
+
}
|
|
2070
|
+
function installedSkillVersions() {
|
|
2071
|
+
const roots = [homedir2(), process.cwd()];
|
|
2072
|
+
const dirs = [".agents", ".claude"];
|
|
2073
|
+
const versions = [];
|
|
2074
|
+
for (const root of roots) {
|
|
2075
|
+
for (const dir of dirs) {
|
|
2076
|
+
const file = path12.join(root, dir, "skills", "artifact-cafe", "SKILL.md");
|
|
2077
|
+
if (!existsSync3(file)) {
|
|
2078
|
+
continue;
|
|
2079
|
+
}
|
|
2080
|
+
try {
|
|
2081
|
+
const found = SKILL_VERSION_PATTERN.exec(readFileSync5(file, "utf8"));
|
|
2082
|
+
if (found?.[1]) {
|
|
2083
|
+
versions.push(found[1]);
|
|
2084
|
+
}
|
|
2085
|
+
} catch {
|
|
2086
|
+
}
|
|
2087
|
+
}
|
|
2088
|
+
}
|
|
2089
|
+
return versions;
|
|
2090
|
+
}
|
|
2091
|
+
function updateChecksDisabled() {
|
|
2092
|
+
return Boolean(
|
|
2093
|
+
process.env.ARTIFACT_CAFE_NO_UPDATE_CHECK ?? process.env.NO_UPDATE_NOTIFIER ?? process.env.CI
|
|
2094
|
+
);
|
|
2095
|
+
}
|
|
2096
|
+
function startUpdateCheck() {
|
|
2097
|
+
if (updateChecksDisabled()) {
|
|
2098
|
+
return () => Promise.resolve();
|
|
2099
|
+
}
|
|
2100
|
+
const pending = (async () => {
|
|
2101
|
+
const cached = readCache();
|
|
2102
|
+
if (cached && Date.now() - cached.checkedAt < CHECK_TTL_MS) {
|
|
2103
|
+
return cached;
|
|
2104
|
+
}
|
|
2105
|
+
const fresh = await fetchLatestVersions(cached);
|
|
2106
|
+
writeCache(fresh);
|
|
2107
|
+
return fresh;
|
|
2108
|
+
})().catch(() => null);
|
|
2109
|
+
return async () => {
|
|
2110
|
+
const latest = await pending;
|
|
2111
|
+
if (!latest) {
|
|
2112
|
+
return;
|
|
2113
|
+
}
|
|
2114
|
+
const notices = [];
|
|
2115
|
+
const current = cliVersion();
|
|
2116
|
+
if (latest.cliLatest && isNewerVersion(latest.cliLatest, current)) {
|
|
2117
|
+
notices.push(
|
|
2118
|
+
`[artifact-cafe] CLI update available: ${current} \u2192 ${latest.cliLatest}. Run commands via \`npx artifact-cafe@latest\`; update a global install with \`npm i -g artifact-cafe@latest\`.`
|
|
2119
|
+
);
|
|
2120
|
+
}
|
|
2121
|
+
if (latest.skillLatest) {
|
|
2122
|
+
const stale = installedSkillVersions().filter(
|
|
2123
|
+
(version) => isNewerVersion(latest.skillLatest, version)
|
|
2124
|
+
).sort((a, b) => isNewerVersion(a, b) ? 1 : -1);
|
|
2125
|
+
if (stale.length > 0) {
|
|
2126
|
+
notices.push(
|
|
2127
|
+
`[artifact-cafe] Skill update available: ${stale[0]} \u2192 ${latest.skillLatest}. Update: \`${SKILL_UPDATE_COMMAND}\` (drop -g for a repo-local copy), then re-read SKILL.md.`
|
|
2128
|
+
);
|
|
2129
|
+
}
|
|
2130
|
+
}
|
|
2131
|
+
if (notices.length > 0) {
|
|
2132
|
+
console.error(`
|
|
2133
|
+
${notices.join("\n")}`);
|
|
2134
|
+
}
|
|
2135
|
+
};
|
|
2136
|
+
}
|
|
2137
|
+
|
|
1874
2138
|
// src/workspaces.ts
|
|
1875
2139
|
async function workspaces(opts) {
|
|
1876
2140
|
const apiUrl2 = (process.env.ARTIFACT_CAFE_URL ?? DEFAULT_API_URL).replace(
|
|
@@ -2292,6 +2556,101 @@ var protect2 = defineCommand({
|
|
|
2292
2556
|
}
|
|
2293
2557
|
}
|
|
2294
2558
|
});
|
|
2559
|
+
var threadStatusCommand = (action) => defineCommand({
|
|
2560
|
+
args: {
|
|
2561
|
+
"api-key": {
|
|
2562
|
+
description: "Authorize with an account API key (default: stored login)",
|
|
2563
|
+
type: "string"
|
|
2564
|
+
},
|
|
2565
|
+
artifact: {
|
|
2566
|
+
description: "Act on an artifact ID instead of the linked folder",
|
|
2567
|
+
type: "string"
|
|
2568
|
+
},
|
|
2569
|
+
dir: {
|
|
2570
|
+
default: ".",
|
|
2571
|
+
description: "Linked directory to authorize from (default: .)",
|
|
2572
|
+
type: "string"
|
|
2573
|
+
},
|
|
2574
|
+
json: { description: "Machine-readable output", type: "boolean" },
|
|
2575
|
+
thread: {
|
|
2576
|
+
description: "Thread id (from `comments --json`)",
|
|
2577
|
+
required: true,
|
|
2578
|
+
type: "positional"
|
|
2579
|
+
}
|
|
2580
|
+
},
|
|
2581
|
+
meta: {
|
|
2582
|
+
description: action === "resolve" ? "Mark a comment thread resolved" : "Reopen a resolved comment thread",
|
|
2583
|
+
name: action
|
|
2584
|
+
},
|
|
2585
|
+
async run({ args }) {
|
|
2586
|
+
try {
|
|
2587
|
+
await changeThreadStatus({
|
|
2588
|
+
action,
|
|
2589
|
+
apiKey: args["api-key"],
|
|
2590
|
+
artifact: args.artifact,
|
|
2591
|
+
dir: args.dir,
|
|
2592
|
+
json: Boolean(args.json),
|
|
2593
|
+
thread: args.thread
|
|
2594
|
+
});
|
|
2595
|
+
} catch (err) {
|
|
2596
|
+
printCliError(err, Boolean(args.json));
|
|
2597
|
+
process.exit(1);
|
|
2598
|
+
}
|
|
2599
|
+
}
|
|
2600
|
+
});
|
|
2601
|
+
var resolve = threadStatusCommand("resolve");
|
|
2602
|
+
var reopen = threadStatusCommand("reopen");
|
|
2603
|
+
var reply = defineCommand({
|
|
2604
|
+
args: {
|
|
2605
|
+
"api-key": {
|
|
2606
|
+
description: "Authorize with an account API key (default: stored login)",
|
|
2607
|
+
type: "string"
|
|
2608
|
+
},
|
|
2609
|
+
artifact: {
|
|
2610
|
+
description: "Act on an artifact ID instead of the linked folder",
|
|
2611
|
+
type: "string"
|
|
2612
|
+
},
|
|
2613
|
+
body: {
|
|
2614
|
+
description: "Reply text (omit to read from stdin)",
|
|
2615
|
+
type: "string"
|
|
2616
|
+
},
|
|
2617
|
+
dir: {
|
|
2618
|
+
default: ".",
|
|
2619
|
+
description: "Linked directory to authorize from (default: .)",
|
|
2620
|
+
type: "string"
|
|
2621
|
+
},
|
|
2622
|
+
json: { description: "Machine-readable output", type: "boolean" },
|
|
2623
|
+
resolve: {
|
|
2624
|
+
description: "Resolve the thread after replying",
|
|
2625
|
+
type: "boolean"
|
|
2626
|
+
},
|
|
2627
|
+
thread: {
|
|
2628
|
+
description: "Thread id (from `comments --json`)",
|
|
2629
|
+
required: true,
|
|
2630
|
+
type: "positional"
|
|
2631
|
+
}
|
|
2632
|
+
},
|
|
2633
|
+
meta: {
|
|
2634
|
+
description: "Reply to a comment thread (as the agent or owner)",
|
|
2635
|
+
name: "reply"
|
|
2636
|
+
},
|
|
2637
|
+
async run({ args }) {
|
|
2638
|
+
try {
|
|
2639
|
+
await replyToThread({
|
|
2640
|
+
apiKey: args["api-key"],
|
|
2641
|
+
artifact: args.artifact,
|
|
2642
|
+
body: args.body,
|
|
2643
|
+
dir: args.dir,
|
|
2644
|
+
json: Boolean(args.json),
|
|
2645
|
+
resolve: Boolean(args.resolve),
|
|
2646
|
+
thread: args.thread
|
|
2647
|
+
});
|
|
2648
|
+
} catch (err) {
|
|
2649
|
+
printCliError(err, Boolean(args.json));
|
|
2650
|
+
process.exit(1);
|
|
2651
|
+
}
|
|
2652
|
+
}
|
|
2653
|
+
});
|
|
2295
2654
|
var open = defineCommand({
|
|
2296
2655
|
args: {
|
|
2297
2656
|
"api-key": {
|
|
@@ -2346,7 +2705,8 @@ var dashboard = defineCommand({
|
|
|
2346
2705
|
var main = defineCommand({
|
|
2347
2706
|
meta: {
|
|
2348
2707
|
description: "Publish AI-generated artifacts for review \u2014 https://artifact.cafe",
|
|
2349
|
-
name: "artifact-cafe"
|
|
2708
|
+
name: "artifact-cafe",
|
|
2709
|
+
version: cliVersion()
|
|
2350
2710
|
},
|
|
2351
2711
|
// Bare `artifact-cafe` (no subcommand) → brand banner + usage. citty
|
|
2352
2712
|
// still calls this parent run *after* a matched subcommand, so bail when
|
|
@@ -2371,8 +2731,13 @@ var main = defineCommand({
|
|
|
2371
2731
|
open,
|
|
2372
2732
|
protect: protect2,
|
|
2373
2733
|
publish: publish2,
|
|
2734
|
+
reopen,
|
|
2735
|
+
reply,
|
|
2736
|
+
resolve,
|
|
2374
2737
|
whoami: whoami2,
|
|
2375
2738
|
workspaces: workspaces2
|
|
2376
2739
|
}
|
|
2377
2740
|
});
|
|
2378
|
-
|
|
2741
|
+
var finishUpdateCheck = startUpdateCheck();
|
|
2742
|
+
await runMain(main);
|
|
2743
|
+
await finishUpdateCheck();
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "artifact-cafe",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.8",
|
|
4
4
|
"description": "Publish AI-generated artifacts for review on artifact.cafe",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"bin": {
|
|
@@ -9,19 +9,19 @@
|
|
|
9
9
|
"files": [
|
|
10
10
|
"dist"
|
|
11
11
|
],
|
|
12
|
+
"scripts": {
|
|
13
|
+
"build": "tsup",
|
|
14
|
+
"typecheck": "tsc --noEmit",
|
|
15
|
+
"dev": "tsup --watch"
|
|
16
|
+
},
|
|
12
17
|
"dependencies": {
|
|
13
18
|
"citty": "^0.1.6",
|
|
14
19
|
"zod": "^4.1.0"
|
|
15
20
|
},
|
|
16
21
|
"devDependencies": {
|
|
22
|
+
"@artifact-cafe/shared": "workspace:*",
|
|
17
23
|
"@types/node": "^24.0.0",
|
|
18
24
|
"tsup": "^8.5.0",
|
|
19
|
-
"typescript": "^5.9.0"
|
|
20
|
-
"@artifact-cafe/shared": "0.1.0"
|
|
21
|
-
},
|
|
22
|
-
"scripts": {
|
|
23
|
-
"build": "tsup",
|
|
24
|
-
"typecheck": "tsc --noEmit",
|
|
25
|
-
"dev": "tsup --watch"
|
|
25
|
+
"typescript": "^5.9.0"
|
|
26
26
|
}
|
|
27
|
-
}
|
|
27
|
+
}
|