@neta-art/cohub-cli 2.3.3 → 2.5.0

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/client.js CHANGED
@@ -1,8 +1,11 @@
1
- import { CohubHttpClient } from "@neta-art/cohub";
1
+ import { CohubHttpClient, readRequestSourceFromEnv } from "@neta-art/cohub";
2
2
  import { clearAuthSession, resolveAccessToken } from "./auth.js";
3
3
  export function createClient() {
4
4
  return new CohubHttpClient({
5
5
  getAccessToken: resolveAccessToken,
6
6
  onUnauthorized: clearAuthSession,
7
+ requestSource: () => readRequestSourceFromEnv(process.env, { via: "cli" }) ?? {
8
+ via: "cli",
9
+ },
7
10
  });
8
11
  }
@@ -229,26 +229,6 @@ function parseMeta(value) {
229
229
  }
230
230
  return parsed;
231
231
  }
232
- function mergeCohubMeta(meta) {
233
- const sessionId = envValue("COHUB_SESSION_ID");
234
- const turnId = envValue("COHUB_TURN_ID");
235
- const toolCallId = envValue("COHUB_TOOL_CALL_ID");
236
- if (!sessionId && !turnId && !toolCallId)
237
- return meta;
238
- const existingCohub = meta?.cohub;
239
- const cohub = existingCohub && typeof existingCohub === "object" && !Array.isArray(existingCohub)
240
- ? existingCohub
241
- : {};
242
- return {
243
- ...(meta ?? {}),
244
- cohub: {
245
- ...cohub,
246
- ...(sessionId ? { sessionId } : {}),
247
- ...(turnId ? { turnId } : {}),
248
- ...(toolCallId ? { toolCallId } : {}),
249
- },
250
- };
251
- }
252
232
  export function registerGenerations(program) {
253
233
  program
254
234
  .command("generate")
@@ -296,7 +276,7 @@ Examples:
296
276
  return error("Generation settings", policyError.message);
297
277
  throw policyError;
298
278
  }
299
- const meta = mergeCohubMeta(parseMeta(opts.meta));
279
+ const meta = parseMeta(opts.meta);
300
280
  const client = createClient();
301
281
  const created = await client.generations.create({
302
282
  spaceId,
@@ -1,21 +1,27 @@
1
1
  import { createClient } from "../client.js";
2
2
  import { table, json as outJson, jsonRequested, error, handleHttp } from "../output.js";
3
3
  const RESOURCE_TYPES = new Set([
4
- "space",
4
+ "turn",
5
5
  "session",
6
+ "space",
6
7
  "checkpoint",
7
8
  ]);
8
9
  const REFERENCE_KINDS = new Set([
9
10
  "session_fork",
10
11
  "space_fork",
11
12
  "checkpoint_fork",
13
+ "mod",
12
14
  "mention",
13
15
  "tool_call",
14
- "mod",
15
- "participant",
16
+ "agent_tool_file_read",
17
+ "agent_tool_file_write",
18
+ "agent_tool_file_edit",
19
+ "agent_tool_file_ls",
20
+ "agent_tool_file_find",
21
+ "agent_tool_file_grep",
16
22
  ]);
17
23
  const DIRECTIONS = new Set(["out", "in", "both"]);
18
- const GROUP_BYS = new Set(["kind", "targetType", "sourceType", "day"]);
24
+ const GROUP_BYS = new Set(["kind", "targetType", "target", "sourceType", "day"]);
19
25
  const UUID_PATTERN = /^[0-9a-f]{8}-[0-9a-f]{4}-[1-5][0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/i;
20
26
  function parseSource(value) {
21
27
  const idx = value.indexOf(":");
@@ -44,25 +50,35 @@ function clampNumber(value, fallback, min, max) {
44
50
  return fallback;
45
51
  return Math.min(Math.max(Math.floor(parsed), min), max);
46
52
  }
53
+ const KINDS_HELP = `Kinds:
54
+ structural: session_fork, space_fork, checkpoint_fork, mod
55
+ content: mention, tool_call
56
+ file access: agent_tool_file_read, agent_tool_file_write, agent_tool_file_edit,
57
+ agent_tool_file_ls, agent_tool_file_find, agent_tool_file_grep`;
47
58
  export function registerReferences(program) {
48
59
  const references = program
49
60
  .command("references")
50
- .description("Inspect resource references (forks, mentions, tool calls, mods, participants)");
61
+ .description("Inspect resource references (forks, mentions, tool calls, mods, file access)")
62
+ .addHelpText("after", "\nAnalysis index for collaboration edges and file heat.\n");
51
63
  references
52
64
  .command("query")
53
65
  .description("List references touching a resource")
54
- .argument("<source>", "Resource selector, e.g. session:<uuid> or space:<uuid>")
66
+ .argument("<source>", "turn:<uuid> | session:<uuid> | space:<uuid> | checkpoint:<uuid>")
55
67
  .option("--direction <dir>", "out | in | both", "both")
56
- .option("--kinds <kinds>", "Comma-separated kinds to include")
68
+ .option("--kinds <kinds>", "Comma-separated kinds (see list below)")
57
69
  .option("--days <n>", "Only references seen within the last N days")
58
70
  .option("--limit <n>", "Maximum rows, 1-500", "200")
59
71
  .option("--json", "Output as JSON")
60
72
  .addHelpText("after", `
61
73
 
74
+ ${KINDS_HELP}
75
+
62
76
  Examples:
77
+ cohub references query turn:<uuid> --kinds agent_tool_file_read,agent_tool_file_write
63
78
  cohub references query session:<uuid> --json
79
+ cohub references query checkpoint:<uuid> --direction out
64
80
  cohub references query space:<uuid> --direction in --kinds mention,tool_call
65
- cohub references query space:<uuid> --kinds mod --days 30
81
+ cohub references query space:<uuid> --kinds agent_tool_file_read --days 30
66
82
  `)
67
83
  .action(async (source, opts) => {
68
84
  const client = createClient();
@@ -86,7 +102,7 @@ Examples:
86
102
  const rows = result.references.map((r) => ({
87
103
  kind: r.kind,
88
104
  source: `${r.sourceType}:${r.sourceId.slice(0, 8)}`,
89
- target: `${r.targetType}:${r.targetId.slice(0, 8)}`,
105
+ target: formatTarget(r.targetType, r.targetId),
90
106
  count: r.count,
91
107
  lastSeen: r.updatedAt.slice(0, 10),
92
108
  }));
@@ -109,15 +125,22 @@ Examples:
109
125
  .command("aggregate")
110
126
  .description("Grouped reference counts for a space")
111
127
  .argument("<spaceId>", "Space id")
112
- .option("--group-by <field>", "kind | targetType | sourceType | day", "kind")
113
- .option("--kinds <kinds>", "Comma-separated kinds to include")
128
+ .option("--group-by <field>", "kind | targetType | target | sourceType | day", "kind")
129
+ .option("--kinds <kinds>", "Comma-separated kinds (see list below)")
114
130
  .option("--days <n>", "Only references seen within the last N days")
131
+ .option("--limit <n>", "Maximum groups, 1-500", "200")
115
132
  .option("--json", "Output as JSON")
116
133
  .addHelpText("after", `
117
134
 
135
+ ${KINDS_HELP}
136
+
137
+ Notes:
138
+ --group-by target: file targets look like {spaceId}:{path}
139
+
118
140
  Examples:
119
141
  cohub references aggregate <spaceId> --json
120
142
  cohub references aggregate <spaceId> --group-by targetType
143
+ cohub references aggregate <spaceId> --group-by target --kinds agent_tool_file_read --limit 20
121
144
  cohub references aggregate <spaceId> --group-by day --days 30
122
145
  `)
123
146
  .action(async (spaceId, opts) => {
@@ -130,7 +153,8 @@ Examples:
130
153
  return error(`Invalid group-by: ${opts.groupBy}`);
131
154
  const kinds = parseKinds(opts.kinds);
132
155
  const days = opts.days ? clampNumber(opts.days, 30, 1, 365) : undefined;
133
- const result = await client.references.aggregate({ spaceId: spaceId.trim(), groupBy, kinds, days });
156
+ const limit = clampNumber(opts.limit, 200, 1, 500);
157
+ const result = await client.references.aggregate({ spaceId: spaceId.trim(), groupBy, kinds, days, limit });
134
158
  if (jsonRequested(opts))
135
159
  return outJson(result);
136
160
  const rows = result.groups.map((g) => ({
@@ -151,3 +175,16 @@ Examples:
151
175
  }
152
176
  });
153
177
  }
178
+ /**
179
+ * Render a target for the table. File targets are `{spaceId}:{path}`; show the
180
+ * short space id plus the full path rather than blindly truncating.
181
+ */
182
+ function formatTarget(targetType, targetId) {
183
+ if (targetType === "file") {
184
+ const idx = targetId.indexOf(":");
185
+ if (idx > 0)
186
+ return `file:${targetId.slice(0, 8)}…${targetId.slice(idx)}`;
187
+ return `file:${targetId}`;
188
+ }
189
+ return `${targetType}:${targetId.slice(0, 8)}`;
190
+ }
@@ -235,7 +235,6 @@ async function sendPrompt(command, words, opts) {
235
235
  const result = await client.space(spaceId).prompt({
236
236
  sessionId,
237
237
  title: sessionId === opts.session ? opts.title : undefined,
238
- source: opts.source?.trim() || "cli",
239
238
  content: promptContent,
240
239
  model: opts.model,
241
240
  provider: opts.provider,
@@ -342,7 +341,6 @@ export function registerPrompt(program) {
342
341
  .description("Send or schedule a prompt in a space")
343
342
  .option("--session <id>", "Target session ID")
344
343
  .option("--title <title>", "Title for a newly created session or schedule")
345
- .option("--source <source>", "Prompt source for newly created sessions", "cli")
346
344
  .option("-m, --model <model>", "Model name")
347
345
  .option("-p, --provider <provider>", "Provider name")
348
346
  .option("--read-only", "Use read-only tools")
@@ -1219,7 +1217,6 @@ function registerSessions(spacesCmd) {
1219
1217
  try {
1220
1218
  const result = await client.space(spaceId).sessions.create({
1221
1219
  title,
1222
- source: "cli",
1223
1220
  labelRefs: opts.label?.length ? opts.label : undefined,
1224
1221
  });
1225
1222
  if (jsonRequested(opts))
@@ -1,6 +1,5 @@
1
1
  import { HttpError } from "@neta-art/cohub";
2
2
  import { createClient } from "../client.js";
3
- import { mergeSourceMeta } from "../env-context.js";
4
3
  import { error, handleHttp, json as outJson, jsonRequested, ok, table } from "../output.js";
5
4
  import { resolveSpace } from "../space.js";
6
5
  import { registerWorkCommerce } from "./work-commerce.js";
@@ -101,14 +100,10 @@ async function confirmDelete(opts) {
101
100
  if (answer !== "y" && answer !== "yes")
102
101
  return error("Cancelled");
103
102
  }
104
- function resolveVersionMeta() {
105
- return mergeSourceMeta(undefined);
106
- }
107
103
  async function publishWorkVersion(id, opts) {
108
104
  const client = createClient();
109
105
  try {
110
- const versionMeta = resolveVersionMeta();
111
- const result = await client.works.publishVersion(id, versionMeta ? { meta: versionMeta } : undefined);
106
+ const result = await client.works.publishVersion(id);
112
107
  if (jsonRequested(opts))
113
108
  return outJson(result);
114
109
  ok(`Work version updated: v${result.version.version}`);
@@ -216,7 +211,6 @@ export function registerWorks(program) {
216
211
  hideCohubBar: opts.hideCohubBar,
217
212
  showCohubBar: opts.showCohubBar,
218
213
  });
219
- const versionMeta = resolveVersionMeta();
220
214
  const input = {
221
215
  spaceId,
222
216
  slug,
@@ -227,7 +221,6 @@ export function registerWorks(program) {
227
221
  workScopes: opts.workScope,
228
222
  allowedViewerScopes: opts.viewerScope,
229
223
  meta,
230
- versionMeta,
231
224
  };
232
225
  try {
233
226
  const result = await client.works.create(input);
@@ -254,7 +247,7 @@ export function registerWorks(program) {
254
247
  meta,
255
248
  });
256
249
  const publishedVersion = status === "published"
257
- ? await client.works.publishVersion(work.id, versionMeta ? { meta: versionMeta } : undefined)
250
+ ? await client.works.publishVersion(work.id)
258
251
  : null;
259
252
  const result = publishedVersion ?? { work };
260
253
  if (jsonRequested(opts))
@@ -328,9 +321,8 @@ export function registerWorks(program) {
328
321
  return error("Nothing to update", "Pass --slug, --file, --dir, --port, --status, --visibility, --work-scope, --viewer-scope, --clear-work-scopes, --clear-viewer-scopes, --meta, --hide-cohub-bar, or --show-cohub-bar.");
329
322
  try {
330
323
  const updated = await client.works.update(id, input);
331
- const versionMeta = resolveVersionMeta();
332
324
  const publishedVersion = nextStatus === "published" && currentWork?.status !== "published"
333
- ? await client.works.publishVersion(updated.work.id, versionMeta ? { meta: versionMeta } : undefined)
325
+ ? await client.works.publishVersion(updated.work.id)
334
326
  : null;
335
327
  const result = publishedVersion ?? updated;
336
328
  if (jsonRequested(opts))
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@neta-art/cohub-cli",
3
- "version": "2.3.3",
3
+ "version": "2.5.0",
4
4
  "description": "CLI for Cohub — spaces, sessions, and agent collaboration.",
5
5
  "type": "module",
6
6
  "license": "Apache-2.0",
@@ -18,7 +18,7 @@
18
18
  "@neta-art/generation": "^0.1.13",
19
19
  "commander": "^15.0.0",
20
20
  "sharp": "^0.35.3",
21
- "@neta-art/cohub": "2.11.2"
21
+ "@neta-art/cohub": "2.13.0"
22
22
  },
23
23
  "publishConfig": {
24
24
  "access": "public"
@@ -1,12 +0,0 @@
1
- /** Read a trimmed non-empty env value. */
2
- export declare function envValue(name: string): string | undefined;
3
- /**
4
- * Merge sandbox provenance into meta under `source`.
5
- * Prefer explicit values; fall back to COHUB_* env vars from the agent/tool runtime.
6
- */
7
- export declare function mergeSourceMeta(meta: Record<string, unknown> | undefined, source?: {
8
- spaceId?: string;
9
- sessionId?: string;
10
- turnId?: string;
11
- toolCallId?: string;
12
- }): Record<string, unknown> | undefined;
@@ -1,33 +0,0 @@
1
- /** Read a trimmed non-empty env value. */
2
- export function envValue(name) {
3
- const value = process.env[name]?.trim();
4
- return value || undefined;
5
- }
6
- /**
7
- * Merge sandbox provenance into meta under `source`.
8
- * Prefer explicit values; fall back to COHUB_* env vars from the agent/tool runtime.
9
- */
10
- export function mergeSourceMeta(meta, source) {
11
- const spaceId = source?.spaceId?.trim() || envValue("COHUB_SPACE_ID");
12
- const sessionId = source?.sessionId?.trim() || envValue("COHUB_SESSION_ID");
13
- const turnId = source?.turnId?.trim() || envValue("COHUB_TURN_ID");
14
- const toolCallId = source?.toolCallId?.trim() || envValue("COHUB_TOOL_CALL_ID");
15
- if (!spaceId && !sessionId && !turnId && !toolCallId)
16
- return meta;
17
- const existingSource = meta?.source;
18
- const nextSource = existingSource && typeof existingSource === "object" && !Array.isArray(existingSource)
19
- ? { ...existingSource }
20
- : {};
21
- if (spaceId)
22
- nextSource.spaceId = spaceId;
23
- if (sessionId)
24
- nextSource.sessionId = sessionId;
25
- if (turnId)
26
- nextSource.turnId = turnId;
27
- if (toolCallId)
28
- nextSource.toolCallId = toolCallId;
29
- return {
30
- ...(meta ?? {}),
31
- source: nextSource,
32
- };
33
- }