@yoyo-bot/cli 0.1.0 → 0.1.2

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/lib/api.d.ts CHANGED
@@ -4,57 +4,95 @@ export declare class ApiError extends Error {
4
4
  constructor(status: number, message: string, body?: unknown | undefined);
5
5
  }
6
6
  export interface BinderSummary {
7
- owner: string;
8
7
  slug: string;
9
- displayName?: string;
8
+ name: string;
10
9
  description?: string;
11
- version?: string;
12
- downloads?: number;
13
- tab?: string;
14
- verification?: "official" | "verified" | "none";
10
+ category?: string;
11
+ latestVersion?: string;
12
+ installCount?: number;
13
+ starCount?: number;
15
14
  tags?: string[];
15
+ featured?: boolean;
16
+ authorName?: string;
17
+ }
18
+ export interface BinderFile {
19
+ id: string;
20
+ filename: string;
21
+ description?: string;
22
+ content: string;
23
+ fileType: string;
24
+ fileSize: number;
25
+ sortOrder: number;
16
26
  }
17
27
  export interface BinderDetail extends BinderSummary {
18
- readme?: string;
19
- latestVersion?: {
28
+ id: string;
29
+ longDescription?: string;
30
+ files?: BinderFile[];
31
+ versions?: Array<{
20
32
  version: string;
21
- tarballUrl?: string;
22
- tarballSha256?: string;
23
- platforms?: string[];
33
+ publishedAt: string;
34
+ }>;
35
+ author?: {
36
+ id: string;
37
+ name: string;
38
+ displayName?: string;
24
39
  };
25
40
  }
26
41
  export interface SearchResult {
27
- items: BinderSummary[];
42
+ binders: BinderSummary[];
28
43
  total: number;
29
- page: number;
30
- pageSize: number;
31
44
  }
32
45
  export interface WhoamiResult {
33
- id: string;
34
- slug: string;
35
- displayName?: string;
36
- email?: string;
46
+ agent: {
47
+ id: string;
48
+ name: string;
49
+ displayName?: string;
50
+ description?: string;
51
+ avatarUrl?: string;
52
+ };
37
53
  }
38
54
  export declare const api: {
39
55
  search: (q: string, page?: number, pageSize?: number) => Promise<SearchResult>;
40
- getBinder: (owner: string, slug: string) => Promise<BinderDetail>;
41
- listBinders: (owner?: string, page?: number, pageSize?: number) => Promise<SearchResult>;
56
+ getBinder: (slug: string) => Promise<{
57
+ binder: BinderDetail;
58
+ }>;
59
+ getInstallBundle: (slug: string) => Promise<{
60
+ instructions: string;
61
+ binder: unknown;
62
+ }>;
63
+ listBinders: (page?: number, pageSize?: number) => Promise<SearchResult>;
64
+ listMyBinders: () => Promise<{
65
+ binders: BinderSummary[];
66
+ }>;
42
67
  whoami: () => Promise<WhoamiResult>;
43
68
  publish: (data: {
44
69
  slug: string;
45
- displayName?: string;
70
+ name: string;
46
71
  description?: string;
47
- version: string;
48
- readme?: string;
72
+ longDescription?: string;
73
+ category?: string;
49
74
  tags?: string[];
50
- tab?: string;
51
- license?: string;
52
- platforms?: string[];
53
- dependencies?: Record<string, string>;
75
+ latestVersion?: string;
76
+ files?: Array<{
77
+ filename: string;
78
+ content: string;
79
+ fileType?: string;
80
+ description?: string;
81
+ }>;
54
82
  }) => Promise<{
55
- id: string;
56
- slug: string;
57
- version: string;
83
+ binder: BinderDetail;
84
+ }>;
85
+ addFiles: (slug: string, files: Array<{
86
+ filename: string;
87
+ content: string;
88
+ fileType?: string;
89
+ description?: string;
90
+ }>) => Promise<{
91
+ success: boolean;
92
+ filesAdded: number;
93
+ }>;
94
+ deleteBinder: (slug: string) => Promise<{
95
+ success: boolean;
58
96
  }>;
59
97
  };
60
98
  //# sourceMappingURL=api.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"api.d.ts","sourceRoot":"","sources":["../../src/lib/api.ts"],"names":[],"mappings":"AAEA,qBAAa,QAAS,SAAQ,KAAK;IAExB,MAAM,EAAE,MAAM;IAEd,IAAI,CAAC,EAAE,OAAO;gBAFd,MAAM,EAAE,MAAM,EACrB,OAAO,EAAE,MAAM,EACR,IAAI,CAAC,EAAE,OAAO,YAAA;CAKxB;AAoCD,MAAM,WAAW,aAAa;IAC5B,KAAK,EAAE,MAAM,CAAC;IACd,IAAI,EAAE,MAAM,CAAC;IACb,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,YAAY,CAAC,EAAE,UAAU,GAAG,UAAU,GAAG,MAAM,CAAC;IAChD,IAAI,CAAC,EAAE,MAAM,EAAE,CAAC;CACjB;AAED,MAAM,WAAW,YAAa,SAAQ,aAAa;IACjD,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,aAAa,CAAC,EAAE;QACd,OAAO,EAAE,MAAM,CAAC;QAChB,UAAU,CAAC,EAAE,MAAM,CAAC;QACpB,aAAa,CAAC,EAAE,MAAM,CAAC;QACvB,SAAS,CAAC,EAAE,MAAM,EAAE,CAAC;KACtB,CAAC;CACH;AAED,MAAM,WAAW,YAAY;IAC3B,KAAK,EAAE,aAAa,EAAE,CAAC;IACvB,KAAK,EAAE,MAAM,CAAC;IACd,IAAI,EAAE,MAAM,CAAC;IACb,QAAQ,EAAE,MAAM,CAAC;CAClB;AAED,MAAM,WAAW,YAAY;IAC3B,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,EAAE,MAAM,CAAC;IACb,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAID,eAAO,MAAM,GAAG;gBACF,MAAM;uBAKC,MAAM,QAAQ,MAAM;0BAKjB,MAAM;;oBASZ;QACd,IAAI,EAAE,MAAM,CAAC;QACb,WAAW,CAAC,EAAE,MAAM,CAAC;QACrB,WAAW,CAAC,EAAE,MAAM,CAAC;QACrB,OAAO,EAAE,MAAM,CAAC;QAChB,MAAM,CAAC,EAAE,MAAM,CAAC;QAChB,IAAI,CAAC,EAAE,MAAM,EAAE,CAAC;QAChB,GAAG,CAAC,EAAE,MAAM,CAAC;QACb,OAAO,CAAC,EAAE,MAAM,CAAC;QACjB,SAAS,CAAC,EAAE,MAAM,EAAE,CAAC;QACrB,YAAY,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;KACvC;YAAmB,MAAM;cAAQ,MAAM;iBAAW,MAAM;;CAC1D,CAAC"}
1
+ {"version":3,"file":"api.d.ts","sourceRoot":"","sources":["../../src/lib/api.ts"],"names":[],"mappings":"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"}
package/dist/lib/api.js CHANGED
@@ -27,7 +27,15 @@ async function request(method, path, opts = {}) {
27
27
  let detail = "";
28
28
  try {
29
29
  const j = (await res.json());
30
- detail = j.message ?? j.error ?? "";
30
+ if (typeof j.error === "string") {
31
+ detail = j.error;
32
+ }
33
+ else if (j.error && typeof j.error === "object") {
34
+ detail = j.error.message || JSON.stringify(j.error);
35
+ }
36
+ else {
37
+ detail = j.message ?? "";
38
+ }
31
39
  }
32
40
  catch { }
33
41
  throw new ApiError(res.status, detail || res.statusText);
@@ -36,19 +44,22 @@ async function request(method, path, opts = {}) {
36
44
  }
37
45
  // ── API calls ──────────────────────────────────────────────────────────────
38
46
  export const api = {
39
- search: (q, page = 1, pageSize = 20) => request("GET", `/binders?q=${encodeURIComponent(q)}&page=${page}&pageSize=${pageSize}`, {
47
+ search: (q, page = 1, pageSize = 20) => request("GET", `/binders?q=${encodeURIComponent(q)}&limit=${pageSize}&offset=${(page - 1) * pageSize}`, {
40
48
  auth: false,
41
49
  }),
42
- getBinder: (owner, slug) => request("GET", `/binders/${encodeURIComponent(owner)}/${encodeURIComponent(slug)}`, {
50
+ getBinder: (slug) => request("GET", `/binders/${encodeURIComponent(slug)}`, {
43
51
  auth: false,
44
52
  }),
45
- listBinders: (owner, page = 1, pageSize = 20) => {
46
- const ownerQ = owner ? `&owner=${encodeURIComponent(owner)}` : "";
47
- return request("GET", `/binders?page=${page}&pageSize=${pageSize}${ownerQ}`, {
48
- auth: false,
49
- });
50
- },
51
- whoami: () => request("GET", "/auth/me"),
53
+ getInstallBundle: (slug) => request("GET", `/binders/${encodeURIComponent(slug)}/install`, {
54
+ auth: false,
55
+ }),
56
+ listBinders: (page = 1, pageSize = 20) => request("GET", `/binders?limit=${pageSize}&offset=${(page - 1) * pageSize}`, {
57
+ auth: false,
58
+ }),
59
+ listMyBinders: () => request("GET", "/binders/my"),
60
+ whoami: () => request("GET", "/agents/me"),
52
61
  publish: (data) => request("POST", "/binders", { body: data }),
62
+ addFiles: (slug, files) => request("POST", `/binders/${encodeURIComponent(slug)}/files`, { body: { files } }),
63
+ deleteBinder: (slug) => request("DELETE", `/binders/${encodeURIComponent(slug)}`),
53
64
  };
54
65
  //# sourceMappingURL=api.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"api.js","sourceRoot":"","sources":["../../src/lib/api.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"api.js","sourceRoot":"","sources":["../../src/lib/api.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,SAAS,EAAE,MAAM,aAAa,CAAC;AAEnD,MAAM,OAAO,QAAS,SAAQ,KAAK;IAExB;IAEA;IAHT,YACS,MAAc,EACrB,OAAe,EACR,IAAc;QAErB,KAAK,CAAC,OAAO,CAAC,CAAC;QAJR,WAAM,GAAN,MAAM,CAAQ;QAEd,SAAI,GAAJ,IAAI,CAAU;QAGrB,IAAI,CAAC,IAAI,GAAG,UAAU,CAAC;IACzB,CAAC;CACF;AAED,KAAK,UAAU,OAAO,CACpB,MAAc,EACd,IAAY,EACZ,OAA2C,EAAE;IAE7C,MAAM,IAAI,GAAG,MAAM,SAAS,EAAE,CAAC;IAC/B,MAAM,GAAG,GAAG,GAAG,IAAI,GAAG,IAAI,EAAE,CAAC;IAC7B,MAAM,OAAO,GAA2B,EAAE,cAAc,EAAE,kBAAkB,EAAE,CAAC;IAE/E,IAAI,IAAI,CAAC,IAAI,KAAK,KAAK,EAAE,CAAC;QACxB,MAAM,GAAG,GAAG,MAAM,SAAS,EAAE,CAAC;QAC9B,IAAI,GAAG;YAAE,OAAO,CAAC,eAAe,CAAC,GAAG,UAAU,GAAG,EAAE,CAAC;IACtD,CAAC;IAED,MAAM,GAAG,GAAG,MAAM,KAAK,CAAC,GAAG,EAAE;QAC3B,MAAM;QACN,OAAO;QACP,IAAI,EAAE,IAAI,CAAC,IAAI,KAAK,SAAS,CAAC,CAAC,CAAC,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,SAAS;KACtE,CAAC,CAAC;IAEH,IAAI,CAAC,GAAG,CAAC,EAAE,EAAE,CAAC;QACZ,IAAI,MAAM,GAAG,EAAE,CAAC;QAChB,IAAI,CAAC;YACH,MAAM,CAAC,GAAG,CAAC,MAAM,GAAG,CAAC,IAAI,EAAE,CAA0C,CAAC;YACtE,IAAI,OAAO,CAAC,CAAC,KAAK,KAAK,QAAQ,EAAE,CAAC;gBAChC,MAAM,GAAG,CAAC,CAAC,KAAK,CAAC;YACnB,CAAC;iBAAM,IAAI,CAAC,CAAC,KAAK,IAAI,OAAO,CAAC,CAAC,KAAK,KAAK,QAAQ,EAAE,CAAC;gBAClD,MAAM,GAAI,CAAC,CAAC,KAA8B,CAAC,OAAO,IAAI,IAAI,CAAC,SAAS,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC;YAChF,CAAC;iBAAM,CAAC;gBACN,MAAM,GAAG,CAAC,CAAC,OAAO,IAAI,EAAE,CAAC;YAC3B,CAAC;QACH,CAAC;QAAC,MAAM,CAAC,CAAA,CAAC;QACV,MAAM,IAAI,QAAQ,CAAC,GAAG,CAAC,MAAM,EAAE,MAAM,IAAI,GAAG,CAAC,UAAU,CAAC,CAAC;IAC3D,CAAC;IAED,OAAO,GAAG,CAAC,IAAI,EAAgB,CAAC;AAClC,CAAC;AAkDD,8EAA8E;AAE9E,MAAM,CAAC,MAAM,GAAG,GAAG;IACjB,MAAM,EAAE,CAAC,CAAS,EAAE,IAAI,GAAG,CAAC,EAAE,QAAQ,GAAG,EAAE,EAAE,EAAE,CAC7C,OAAO,CAAe,KAAK,EAAE,cAAc,kBAAkB,CAAC,CAAC,CAAC,UAAU,QAAQ,WAAW,CAAC,IAAI,GAAG,CAAC,CAAC,GAAG,QAAQ,EAAE,EAAE;QACpH,IAAI,EAAE,KAAK;KACZ,CAAC;IAEJ,SAAS,EAAE,CAAC,IAAY,EAAE,EAAE,CAC1B,OAAO,CAA2B,KAAK,EAAE,YAAY,kBAAkB,CAAC,IAAI,CAAC,EAAE,EAAE;QAC/E,IAAI,EAAE,KAAK;KACZ,CAAC;IAEJ,gBAAgB,EAAE,CAAC,IAAY,EAAE,EAAE,CACjC,OAAO,CAA4C,KAAK,EAAE,YAAY,kBAAkB,CAAC,IAAI,CAAC,UAAU,EAAE;QACxG,IAAI,EAAE,KAAK;KACZ,CAAC;IAEJ,WAAW,EAAE,CAAC,IAAI,GAAG,CAAC,EAAE,QAAQ,GAAG,EAAE,EAAE,EAAE,CACvC,OAAO,CAAe,KAAK,EAAE,kBAAkB,QAAQ,WAAW,CAAC,IAAI,GAAG,CAAC,CAAC,GAAG,QAAQ,EAAE,EAAE;QACzF,IAAI,EAAE,KAAK;KACZ,CAAC;IAEJ,aAAa,EAAE,GAAG,EAAE,CAClB,OAAO,CAA+B,KAAK,EAAE,aAAa,CAAC;IAE7D,MAAM,EAAE,GAAG,EAAE,CAAC,OAAO,CAAe,KAAK,EAAE,YAAY,CAAC;IAExD,OAAO,EAAE,CAAC,IAST,EAAE,EAAE,CAAC,OAAO,CAA2B,MAAM,EAAE,UAAU,EAAE,EAAE,IAAI,EAAE,IAAI,EAAE,CAAC;IAE3E,QAAQ,EAAE,CAAC,IAAY,EAAE,KAA4F,EAAE,EAAE,CACvH,OAAO,CAA2C,MAAM,EAAE,YAAY,kBAAkB,CAAC,IAAI,CAAC,QAAQ,EAAE,EAAE,IAAI,EAAE,EAAE,KAAK,EAAE,EAAE,CAAC;IAE9H,YAAY,EAAE,CAAC,IAAY,EAAE,EAAE,CAC7B,OAAO,CAAuB,QAAQ,EAAE,YAAY,kBAAkB,CAAC,IAAI,CAAC,EAAE,CAAC;CAClF,CAAC"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@yoyo-bot/cli",
3
- "version": "0.1.0",
3
+ "version": "0.1.2",
4
4
  "description": "YoYo CLI — search, install, fork, and publish binders for AI agents. The universal binder registry.",
5
5
  "type": "module",
6
6
  "bin": {
@@ -1,8 +1,6 @@
1
1
  import { writeFile, mkdir } from "node:fs/promises";
2
2
  import { join, resolve } from "node:path";
3
3
  import { homedir } from "node:os";
4
- import { createHash } from "node:crypto";
5
- import { unlink } from "node:fs/promises";
6
4
  import pc from "picocolors";
7
5
  import { api, ApiError } from "../lib/api.js";
8
6
 
@@ -17,12 +15,17 @@ function defaultBindRoot(): string {
17
15
  return join(homedir(), ".yoyo", "binders");
18
16
  }
19
17
 
20
- function parseRef(ref: string): { owner: string; slug: string } {
18
+ // Bug fix #5: Accept both "owner/slug" and just "slug"
19
+ function parseRef(ref: string): { slug: string } {
21
20
  const parts = ref.split("/");
22
- if (parts.length !== 2 || !parts[0] || !parts[1]) {
23
- throw new Error(`Invalid binder ref "${ref}". Expected <owner>/<slug>`);
21
+ if (parts.length === 2) {
22
+ // owner/slug format use just the slug
23
+ return { slug: parts[1] };
24
24
  }
25
- return { owner: parts[0], slug: parts[1] };
25
+ if (parts.length === 1 && parts[0]) {
26
+ return { slug: parts[0] };
27
+ }
28
+ throw new Error(`Invalid binder ref "${ref}". Use: yoyo bind <slug> or yoyo bind <owner>/<slug>`);
26
29
  }
27
30
 
28
31
  function formatBytes(n: number): string {
@@ -32,50 +35,39 @@ function formatBytes(n: number): string {
32
35
  }
33
36
 
34
37
  export async function bindCommand(ref: string, opts: BindOptions): Promise<void> {
35
- let owner: string, slug: string;
38
+ let slug: string;
36
39
  try {
37
- ({ owner, slug } = parseRef(ref));
40
+ ({ slug } = parseRef(ref));
38
41
  } catch (err) {
39
42
  console.error(pc.red(String(err)));
40
43
  process.exit(1);
41
44
  }
42
45
 
43
- if (!opts.json) process.stdout.write(pc.dim(`Fetching ${ref}…\n`));
46
+ if (!opts.json) process.stdout.write(pc.dim(`Fetching ${slug}…\n`));
44
47
 
45
- let binder;
48
+ let binderData;
46
49
  try {
47
- binder = await api.getBinder(owner, slug);
50
+ binderData = await api.getBinder(slug);
48
51
  } catch (err) {
49
52
  if (err instanceof ApiError && err.status === 404) {
50
- console.error(pc.red(`Binder not found: ${ref}`));
53
+ console.error(pc.red(`Binder not found: ${slug}`));
51
54
  } else {
52
55
  console.error(pc.red(`API error: ${String(err)}`));
53
56
  }
54
57
  process.exit(1);
55
58
  }
56
59
 
57
- const spine = binder.latestVersion;
58
- if (!spine) {
59
- console.error(pc.red(`Binder ${ref} has no published versions.`));
60
- process.exit(1);
61
- }
62
-
63
- const bindDir = join(opts.dir ? resolve(opts.dir) : defaultBindRoot(), owner, slug);
60
+ const binder = binderData.binder;
61
+ const bindDir = join(opts.dir ? resolve(opts.dir) : defaultBindRoot(), slug);
64
62
 
65
63
  if (opts.json) {
66
- console.log(JSON.stringify({ ref, bindDir, dryRun: opts.dryRun ?? false, binder }, null, 2));
64
+ console.log(JSON.stringify({ ref, slug, bindDir, dryRun: opts.dryRun ?? false, binder }, null, 2));
67
65
  return;
68
66
  }
69
67
 
70
- const badge =
71
- binder.verification === "official"
72
- ? pc.yellow(" ✦ Official")
73
- : binder.verification === "verified"
74
- ? pc.green(" ✓ Verified")
75
- : "";
76
-
77
- console.log(`\n${pc.bold(binder.displayName ?? ref)}${badge} ${pc.dim(`v${spine.version}`)}`);
68
+ console.log(`\n${pc.bold(binder.name ?? slug)} ${pc.dim(`v${binder.latestVersion || "1.0.0"}`)}`);
78
69
  if (binder.description) console.log(pc.dim(binder.description.slice(0, 80)));
70
+ if (binder.starCount) console.log(pc.yellow(`★ ${binder.starCount}`));
79
71
  console.log(pc.dim("─".repeat(50)));
80
72
  console.log(` ${pc.dim("Bind to")} ${pc.dim(bindDir)}`);
81
73
  console.log();
@@ -89,59 +81,37 @@ export async function bindCommand(ref: string, opts: BindOptions): Promise<void>
89
81
 
90
82
  // Write manifest
91
83
  const manifest = {
92
- name: slug,
93
- owner,
94
- fullName: `${owner}/${slug}`,
95
- version: spine.version,
84
+ slug,
85
+ name: binder.name,
86
+ version: binder.latestVersion || "1.0.0",
96
87
  description: binder.description,
97
- tab: binder.tab,
88
+ category: binder.category,
98
89
  tags: binder.tags ?? [],
99
90
  boundAt: new Date().toISOString(),
100
- tarballUrl: spine.tarballUrl,
101
- tarballSha256: spine.tarballSha256,
102
91
  };
103
92
  await writeFile(join(bindDir, "binder.json"), JSON.stringify(manifest, null, 2) + "\n", "utf8");
104
93
  console.log(` ${pc.green("✓")} binder.json`);
105
94
 
106
- // Download tarball with SHA256 verification
107
- if (spine.tarballUrl) {
108
- const tarPath = join(bindDir, `${slug}-${spine.version}.tar.gz`);
109
- process.stdout.write(` ${pc.dim("↓ tarball…")}`);
110
- try {
111
- const res = await fetch(spine.tarballUrl);
112
- if (res.ok && res.body) {
113
- const reader = res.body.getReader();
114
- const chunks: Uint8Array[] = [];
115
- let total = 0;
116
- for (;;) {
117
- const { done, value } = await reader.read();
118
- if (done) break;
119
- chunks.push(value);
120
- total += value.byteLength;
121
- }
122
- const buf = Buffer.concat(chunks, total);
123
-
124
- if (spine.tarballSha256) {
125
- const actual = createHash("sha256").update(buf).digest("hex");
126
- if (actual !== spine.tarballSha256) {
127
- process.stdout.write(`\r ${pc.red("✗")} tarball SHA256 mismatch — aborting\n`);
128
- console.error(pc.dim(` expected: ${spine.tarballSha256}\n got: ${actual}`));
129
- await unlink(tarPath).catch(() => {});
130
- process.exit(1);
131
- }
132
- }
133
-
134
- await writeFile(tarPath, buf);
135
- process.stdout.write(`\r ${pc.green("✓")} tarball (${pc.dim(formatBytes(total))})\n`);
136
- } else {
137
- process.stdout.write(`\r ${pc.dim("~ tarball skipped")}\n`);
138
- }
139
- } catch {
140
- process.stdout.write(`\r ${pc.dim("~ tarball unavailable")}\n`);
95
+ // Write files
96
+ if (binder.files && binder.files.length > 0) {
97
+ for (const f of binder.files) {
98
+ const filePath = join(bindDir, f.filename);
99
+ // Create subdirectories if filename contains slashes
100
+ const dir = join(bindDir, f.filename.split("/").slice(0, -1).join("/"));
101
+ if (dir !== bindDir) await mkdir(dir, { recursive: true });
102
+
103
+ await writeFile(filePath, f.content, "utf8");
104
+ console.log(` ${pc.green("✓")} ${f.filename} ${pc.dim(`(${formatBytes(f.fileSize || f.content.length)})`)}`);
141
105
  }
142
106
  }
143
107
 
108
+ // Write longDescription as README.md
109
+ if (binder.longDescription) {
110
+ await writeFile(join(bindDir, "README.md"), binder.longDescription, "utf8");
111
+ console.log(` ${pc.green("✓")} README.md`);
112
+ }
113
+
144
114
  console.log();
145
- console.log(pc.green(`Bound ${ref}@${spine.version}`));
115
+ console.log(pc.green(`Bound ${slug}@${binder.latestVersion || "1.0.0"}`));
146
116
  console.log(pc.dim(`Location: ${bindDir}`));
147
117
  }
@@ -1,13 +1,13 @@
1
1
  import pc from "picocolors";
2
2
  import { api } from "../lib/api.js";
3
3
 
4
- export async function listCommand(opts: { owner?: string; page?: string; json?: boolean }): Promise<void> {
4
+ export async function listCommand(opts: { page?: string; json?: boolean }): Promise<void> {
5
5
  const page = Number(opts.page ?? 1);
6
6
  const pageSize = 20;
7
7
 
8
8
  let result;
9
9
  try {
10
- result = await api.listBinders(opts.owner, page, pageSize);
10
+ result = await api.listBinders(page, pageSize);
11
11
  } catch (err) {
12
12
  console.error(pc.red(`Failed to list binders: ${String(err)}`));
13
13
  process.exit(1);
@@ -18,21 +18,21 @@ export async function listCommand(opts: { owner?: string; page?: string; json?:
18
18
  return;
19
19
  }
20
20
 
21
- if (result.items.length === 0) {
21
+ const binders = result.binders ?? [];
22
+
23
+ if (binders.length === 0) {
22
24
  console.log(pc.dim("No binders found."));
23
25
  return;
24
26
  }
25
27
 
26
- const title = opts.owner ? `Binders by ${opts.owner}` : "All binders";
27
- console.log(pc.bold(`\n${title}`) + pc.dim(` (${result.total} total)\n`));
28
+ console.log(pc.bold(`\nBinders`) + pc.dim(` (${result.total} total)\n`));
28
29
 
29
- for (const b of result.items) {
30
- const name = pc.cyan(`${b.owner}/${b.slug}`);
31
- const ver = b.version ? pc.dim(`v${b.version}`) : "";
32
- const badge =
33
- b.verification === "official" ? pc.yellow(" ✦") : b.verification === "verified" ? pc.green(" ✓") : "";
34
- const dl = b.downloads != null ? pc.dim(` · ${b.downloads.toLocaleString()} downloads`) : "";
35
- console.log(` ${name}${badge} ${ver}${dl}`);
30
+ for (const b of binders) {
31
+ const name = pc.cyan(b.slug);
32
+ const ver = b.latestVersion ? pc.dim(`v${b.latestVersion}`) : "";
33
+ const stars = b.starCount ? pc.yellow(` ★${b.starCount}`) : "";
34
+ const installs = b.installCount ? pc.dim(` ↓${b.installCount}`) : "";
35
+ console.log(` ${name}${stars}${installs} ${ver}`);
36
36
  if (b.description) console.log(` ${pc.dim(b.description.slice(0, 80))}`);
37
37
  console.log();
38
38
  }
@@ -14,9 +14,10 @@ interface PublishOptions {
14
14
  interface BinderManifest {
15
15
  slug: string;
16
16
  displayName?: string;
17
+ name?: string;
17
18
  description?: string;
18
19
  version: string;
19
- tab?: string;
20
+ category?: string;
20
21
  tags?: string[];
21
22
  platforms?: string[];
22
23
  license?: string;
@@ -56,34 +57,58 @@ export async function publishCommand(opts: PublishOptions): Promise<void> {
56
57
  process.exit(1);
57
58
  }
58
59
 
59
- // Read page.md as readme if present
60
- let readme: string | undefined;
60
+ // Read page.md or README.md as longDescription
61
+ let longDescription: string | undefined;
61
62
  const pagePath = join(cwd, "page.md");
62
63
  if (existsSync(pagePath)) {
63
- readme = await readFile(pagePath, "utf8");
64
+ longDescription = await readFile(pagePath, "utf8");
64
65
  } else {
65
66
  const readmePath = join(cwd, "README.md");
66
- if (existsSync(readmePath)) readme = await readFile(readmePath, "utf8");
67
+ if (existsSync(readmePath)) longDescription = await readFile(readmePath, "utf8");
67
68
  }
68
69
 
70
+ // Collect files from the binder directory
71
+ const files: Array<{ filename: string; content: string; fileType?: string; description?: string }> = [];
72
+
73
+ // Include common binder files if they exist
74
+ const filePatterns = [
75
+ { path: "binder.md", fileType: "skill" },
76
+ { path: "SKILL.md", fileType: "skill" },
77
+ { path: "config.yaml", fileType: "config" },
78
+ { path: "config.json", fileType: "config" },
79
+ ];
80
+
81
+ for (const fp of filePatterns) {
82
+ const fullPath = join(cwd, fp.path);
83
+ if (existsSync(fullPath)) {
84
+ const content = await readFile(fullPath, "utf8");
85
+ files.push({ filename: fp.path, content, fileType: fp.fileType });
86
+ }
87
+ }
88
+
89
+ // Bug fix #1: Map displayName → name (API requires "name", manifest uses "displayName")
90
+ const name = manifest.name || manifest.displayName || manifest.slug;
91
+
92
+ const payload = {
93
+ slug: manifest.slug,
94
+ name,
95
+ description: manifest.description,
96
+ longDescription,
97
+ category: manifest.category,
98
+ tags: manifest.tags ?? [],
99
+ latestVersion: manifest.version,
100
+ files: files.length > 0 ? files : undefined,
101
+ };
102
+
69
103
  if (opts.dryRun || opts.json) {
70
- const payload = {
71
- slug: manifest.slug,
72
- displayName: manifest.displayName,
73
- description: manifest.description,
74
- version: manifest.version,
75
- readme,
76
- tags: manifest.tags ?? [],
77
- tab: manifest.tab,
78
- license: manifest.license,
79
- platforms: manifest.platforms ?? [],
80
- dependencies: manifest.dependencies ?? {},
81
- };
82
104
  if (opts.json) {
83
105
  console.log(JSON.stringify({ dryRun: opts.dryRun ?? false, payload }, null, 2));
84
106
  } else {
85
107
  console.log(pc.yellow("Dry run — would publish:"));
86
108
  console.log(` ${manifest.slug}@${manifest.version}`);
109
+ console.log(` name: ${name}`);
110
+ if (longDescription) console.log(` longDescription: ${longDescription.length} chars`);
111
+ if (files.length) console.log(` files: ${files.map(f => f.filename).join(", ")}`);
87
112
  }
88
113
  return;
89
114
  }
@@ -91,21 +116,12 @@ export async function publishCommand(opts: PublishOptions): Promise<void> {
91
116
  console.log(pc.dim(`Publishing ${manifest.slug}@${manifest.version}…`));
92
117
 
93
118
  try {
94
- const result = await api.publish({
95
- slug: manifest.slug,
96
- displayName: manifest.displayName,
97
- description: manifest.description,
98
- version: manifest.version,
99
- readme,
100
- tags: manifest.tags ?? [],
101
- tab: manifest.tab,
102
- license: manifest.license,
103
- platforms: manifest.platforms ?? [],
104
- dependencies: manifest.dependencies ?? {},
105
- });
106
-
107
- console.log(pc.green(`\nPublished ${result.slug}@${result.version}`));
108
- console.log(pc.dim(`ID: ${result.id}`));
119
+ const result = await api.publish(payload);
120
+
121
+ console.log(pc.green(`\nPublished ${result.binder.slug}@${result.binder.latestVersion || manifest.version}`));
122
+ console.log(pc.dim(`ID: ${result.binder.id}`));
123
+ if (files.length) console.log(pc.dim(`Files: ${files.length} uploaded`));
124
+ console.log(pc.dim(`View: https://yoyo.bot/binders/${manifest.slug}`));
109
125
  } catch (err) {
110
126
  if (err instanceof ApiError) {
111
127
  console.error(pc.red(`Publish failed (${err.status}): ${err.message}`));
@@ -17,18 +17,22 @@ export async function searchCommand(query: string, opts: { limit?: string; json?
17
17
  return;
18
18
  }
19
19
 
20
- if (result.items.length === 0) {
20
+ // Bug fix #3: API returns result.binders, not result.items
21
+ const binders = result.binders ?? [];
22
+
23
+ if (binders.length === 0) {
21
24
  console.log(pc.dim(`No results for "${query}"`));
22
25
  return;
23
26
  }
24
27
 
25
28
  console.log(pc.bold(`\nSearch results for "${query}"`) + pc.dim(` (${result.total} total)\n`));
26
29
 
27
- for (const b of result.items) {
28
- const name = pc.cyan(`${b.owner}/${b.slug}`);
29
- const ver = b.version ? pc.dim(`v${b.version}`) : "";
30
- const badge = b.verification === "official" ? pc.yellow(" ✦") : b.verification === "verified" ? pc.green(" ✓") : "";
31
- console.log(` ${name}${badge} ${ver}`);
30
+ for (const b of binders) {
31
+ const name = pc.cyan(b.slug);
32
+ const ver = b.latestVersion ? pc.dim(`v${b.latestVersion}`) : "";
33
+ const stars = b.starCount ? pc.yellow(` ★${b.starCount}`) : "";
34
+ const installs = b.installCount ? pc.dim(` ↓${b.installCount}`) : "";
35
+ console.log(` ${name}${stars}${installs} ${ver}`);
32
36
  if (b.description) {
33
37
  console.log(` ${pc.dim(b.description.slice(0, 80))}`);
34
38
  }
@@ -9,26 +9,32 @@ export async function whoamiCommand(opts: { json?: boolean }): Promise<void> {
9
9
  process.exit(1);
10
10
  }
11
11
 
12
- let user;
12
+ let result;
13
13
  try {
14
- user = await api.whoami();
14
+ result = await api.whoami();
15
15
  } catch (err) {
16
16
  if (err instanceof ApiError && err.status === 401) {
17
17
  console.error(pc.red("Invalid or expired API key. Run: yoyo auth"));
18
+ } else if (err instanceof ApiError) {
19
+ // Bug fix #4: properly stringify the error (was showing [object Object])
20
+ console.error(pc.red(`Error (${err.status}): ${err.message}`));
18
21
  } else {
19
22
  console.error(pc.red(`Error: ${String(err)}`));
20
23
  }
21
24
  process.exit(1);
22
25
  }
23
26
 
27
+ const agent = result.agent;
28
+
24
29
  if (opts.json) {
25
- console.log(JSON.stringify(user, null, 2));
30
+ console.log(JSON.stringify(agent, null, 2));
26
31
  return;
27
32
  }
28
33
 
29
34
  console.log();
30
- console.log(` ${pc.bold(user.displayName ?? user.slug)}`);
31
- console.log(` ${pc.dim("Slug")} ${user.slug}`);
32
- if (user.email) console.log(` ${pc.dim("Email")} ${user.email}`);
35
+ console.log(` ${pc.bold(agent.displayName ?? agent.name)}`);
36
+ console.log(` ${pc.dim("Name")} ${agent.name}`);
37
+ if (agent.description) console.log(` ${pc.dim("About")} ${agent.description}`);
38
+ console.log(` ${pc.dim("ID")} ${agent.id}`);
33
39
  console.log();
34
40
  }
package/src/index.ts CHANGED
@@ -22,7 +22,7 @@ program
22
22
  .action((query: string, opts) => searchCommand(query, opts));
23
23
 
24
24
  program
25
- .command("bind <owner/slug>")
25
+ .command("bind <slug>")
26
26
  .description("Bind (install) a binder to ~/.yoyo/binders/")
27
27
  .option("-v, --version <ver>", "specific version")
28
28
  .option("-d, --dir <path>", "bind root directory")
@@ -40,7 +40,6 @@ program
40
40
  program
41
41
  .command("list")
42
42
  .description("List binders in the registry")
43
- .option("--owner <slug>", "filter by owner")
44
43
  .option("--page <n>", "page number", "1")
45
44
  .option("--json", "output JSON")
46
45
  .action((opts) => listCommand(opts));