Files
united-workforce/packages/cli-uwf/src/commands/cas.ts
T
xiaoju 52282e1960 feat: built-in uwf cas commands replacing json-cas passthrough
- get, cat, put, has, list, refs, walk, schema list, schema get
- All commands auto-resolve store to ~/.uncaged/workflow/cas
- No external json-cas CLI dependency needed
- Agent-friendly: uwf cas --help shows all available subcommands

Refs #319, Closes #320

小橘 🍊(NEKO Team)
2026-05-18 12:40:15 +00:00

166 lines
4.3 KiB
TypeScript

import { readFileSync } from "node:fs";
import { join } from "node:path";
import type { Hash, JSONSchema, Store } from "@uncaged/json-cas";
import { bootstrap, getSchema, refs, walk } from "@uncaged/json-cas";
import { createFsStore } from "@uncaged/json-cas-fs";
// ---- Helpers ----
function openStore(storageRoot: string): Store {
return createFsStore(join(storageRoot, "cas"));
}
function out(data: unknown, compact = false): void {
console.log(compact ? JSON.stringify(data) : JSON.stringify(data, null, 2));
}
function readJsonArg(fileOrInline: string): unknown {
// Try as inline JSON first, then as file path
try {
return JSON.parse(fileOrInline);
} catch {
try {
return JSON.parse(readFileSync(fileOrInline, "utf-8"));
} catch (e) {
throw new Error(`Cannot parse JSON from "${fileOrInline}": ${e}`);
}
}
}
// ---- Commands ----
export async function cmdCasGet(
storageRoot: string,
hash: string,
opts: { json?: boolean },
): Promise<void> {
const store = openStore(storageRoot);
const node = store.get(hash);
if (node === null) {
throw new Error(`Node not found: ${hash}`);
}
out(node, opts.json);
}
export async function cmdCasCat(
storageRoot: string,
hash: string,
opts: { payload?: boolean; json?: boolean },
): Promise<void> {
const store = openStore(storageRoot);
const node = store.get(hash);
if (node === null) {
throw new Error(`Node not found: ${hash}`);
}
out(opts.payload ? node.payload : node, opts.json);
}
export async function cmdCasPut(
storageRoot: string,
typeHash: string,
data: string,
opts: { json?: boolean },
): Promise<void> {
const store = openStore(storageRoot);
const payload = readJsonArg(data);
const hash = store.put(typeHash, payload);
console.log(hash);
}
export async function cmdCasHas(
storageRoot: string,
hash: string,
): Promise<void> {
const store = openStore(storageRoot);
console.log(String(store.has(hash)));
}
export async function cmdCasList(storageRoot: string): Promise<void> {
const store = openStore(storageRoot);
for (const hash of store.list()) {
console.log(hash);
}
}
export async function cmdCasRefs(storageRoot: string, hash: string): Promise<void> {
const store = openStore(storageRoot);
const node = store.get(hash);
if (node === null) {
throw new Error(`Node not found: ${hash}`);
}
const refHashes = refs(store, node);
for (const r of refHashes) {
console.log(r);
}
}
export async function cmdCasWalk(
storageRoot: string,
hash: string,
opts: { format?: string },
): Promise<void> {
const store = openStore(storageRoot);
if (opts.format === "tree") {
const childMap = new Map<Hash, Hash[]>();
walk(store, hash, (h, node) => {
childMap.set(h, refs(store, node));
});
const printed = new Set<Hash>();
function printNode(h: Hash, prefix: string, isLast: boolean): void {
const connector = prefix === "" ? "" : isLast ? "└── " : "├── ";
if (printed.has(h)) {
console.log(`${prefix}${connector}${h} (seen)`);
return;
}
printed.add(h);
console.log(`${prefix}${connector}${h}`);
const kids = childMap.get(h) ?? [];
const childPrefix = prefix === "" ? "" : prefix + (isLast ? " " : "│ ");
for (let i = 0; i < kids.length; i++) {
printNode(kids[i] as Hash, childPrefix, i === kids.length - 1);
}
}
printNode(hash, "", true);
} else {
walk(store, hash, (h) => {
console.log(h);
});
}
}
export async function cmdCasSchemaList(storageRoot: string): Promise<void> {
const store = openStore(storageRoot);
const metaHash = await bootstrap(store);
for (const hash of store.list()) {
if (hash === metaHash) continue;
const node = store.get(hash);
if (node !== null && node.type === metaHash) {
const schema = node.payload as JSONSchema;
const name =
(schema.title as string | undefined) ??
(schema.description as string | undefined) ??
"(unnamed)";
console.log(`${hash} ${name}`);
}
}
}
export async function cmdCasSchemaGet(
storageRoot: string,
hash: string,
opts: { json?: boolean },
): Promise<void> {
const store = openStore(storageRoot);
const schema = getSchema(store, hash);
if (schema === null) {
throw new Error(`Schema not found: ${hash}`);
}
out(schema, opts.json);
}