@rk0429/agentic-relay 2.0.1 → 2.0.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.
Files changed (2) hide show
  1. package/dist/relay.mjs +131 -35
  2. package/package.json +1 -1
package/dist/relay.mjs CHANGED
@@ -2208,13 +2208,21 @@ var init_access_control = __esm({
2208
2208
  case "escalate_task":
2209
2209
  case "release_task":
2210
2210
  case "decompose_task": {
2211
- if (task.assignee !== agent_id) {
2212
- throw new TasksError("access_denied", "only assignee can perform this action", {
2213
- action,
2214
- task_id,
2215
- agent_id,
2216
- assignee: task.assignee
2217
- });
2211
+ if (task.assignee !== agent_id && !this.isCreatorOrAbove(task, agent_id)) {
2212
+ const parent = task.parent_task_id ? this.get_task(task.parent_task_id) : null;
2213
+ throw new TasksError(
2214
+ "access_denied",
2215
+ "only assignee, creator, or parent assignee can perform this action",
2216
+ {
2217
+ action,
2218
+ task_id,
2219
+ agent_id,
2220
+ assignee: task.assignee,
2221
+ created_by: task.created_by,
2222
+ parent_task_id: task.parent_task_id,
2223
+ parent_assignee: parent?.assignee ?? null
2224
+ }
2225
+ );
2218
2226
  }
2219
2227
  return;
2220
2228
  }
@@ -2268,13 +2276,32 @@ var init_access_control = __esm({
2268
2276
  return;
2269
2277
  }
2270
2278
  case "archive_task": {
2271
- if (task.created_by !== agent_id) {
2272
- throw new TasksError("access_denied", "only creator can archive task", {
2273
- action,
2274
- task_id,
2275
- agent_id,
2276
- created_by: task.created_by
2277
- });
2279
+ if (task.assignee === agent_id && !this.isCreatorOrAbove(task, agent_id)) {
2280
+ throw new TasksError(
2281
+ "access_denied",
2282
+ "assignee cannot archive own task",
2283
+ {
2284
+ action,
2285
+ task_id,
2286
+ agent_id,
2287
+ assignee: task.assignee
2288
+ }
2289
+ );
2290
+ }
2291
+ if (!this.isCreatorOrAbove(task, agent_id)) {
2292
+ const parent = task.parent_task_id ? this.get_task(task.parent_task_id) : null;
2293
+ throw new TasksError(
2294
+ "access_denied",
2295
+ "only creator or parent assignee can archive task",
2296
+ {
2297
+ action,
2298
+ task_id,
2299
+ agent_id,
2300
+ created_by: task.created_by,
2301
+ parent_task_id: task.parent_task_id,
2302
+ parent_assignee: parent?.assignee ?? null
2303
+ }
2304
+ );
2278
2305
  }
2279
2306
  return;
2280
2307
  }
@@ -2353,6 +2380,18 @@ var init_access_control = __esm({
2353
2380
  const task = this.get_task(task_id);
2354
2381
  return task.assignee === agent_id;
2355
2382
  }
2383
+ isCreatorOrAbove(task, agent_id) {
2384
+ if (task.created_by === agent_id) {
2385
+ return true;
2386
+ }
2387
+ if (task.parent_task_id) {
2388
+ const parent = this.get_task(task.parent_task_id);
2389
+ if (parent.assignee === agent_id) {
2390
+ return true;
2391
+ }
2392
+ }
2393
+ return false;
2394
+ }
2356
2395
  get_task(task_id) {
2357
2396
  const row = this.db.prepare(
2358
2397
  `
@@ -2917,7 +2956,7 @@ function nowIso5() {
2917
2956
  return (/* @__PURE__ */ new Date()).toISOString();
2918
2957
  }
2919
2958
  function parseJsonObject(value) {
2920
- if (!value) {
2959
+ if (!value || value === "null") {
2921
2960
  return null;
2922
2961
  }
2923
2962
  return JSON.parse(value);
@@ -2959,7 +2998,7 @@ var init_project_manager = __esm({
2959
2998
  id,
2960
2999
  input.name,
2961
3000
  input.description ?? "",
2962
- JSON.stringify(input.metadata ?? null),
3001
+ input.metadata ? JSON.stringify(input.metadata) : null,
2963
3002
  wip_limit,
2964
3003
  1,
2965
3004
  now,
@@ -4046,7 +4085,7 @@ function normalizeAcceptanceCriteria(criteria) {
4046
4085
  return criteria ?? [];
4047
4086
  }
4048
4087
  function parseJsonObject2(value) {
4049
- if (!value) {
4088
+ if (!value || value === "null") {
4050
4089
  return null;
4051
4090
  }
4052
4091
  return JSON.parse(value);
@@ -4147,7 +4186,7 @@ var init_task_manager = __esm({
4147
4186
  input.sprint_id ?? null,
4148
4187
  input.assignee ?? null,
4149
4188
  JSON.stringify(acceptanceCriteria),
4150
- JSON.stringify(input.metadata ?? null),
4189
+ input.metadata ? JSON.stringify(input.metadata) : null,
4151
4190
  1,
4152
4191
  input.created_by ?? null,
4153
4192
  now,
@@ -4570,7 +4609,7 @@ function nowIso10() {
4570
4609
  return (/* @__PURE__ */ new Date()).toISOString();
4571
4610
  }
4572
4611
  function parseJson(value, fallback) {
4573
- if (!value) {
4612
+ if (!value || value === "null") {
4574
4613
  return fallback;
4575
4614
  }
4576
4615
  return JSON.parse(value);
@@ -5917,8 +5956,8 @@ var init_tasks_runtime = __esm({
5917
5956
  input.project_id,
5918
5957
  input.trigger_type,
5919
5958
  JSON.stringify(input.assessment),
5920
- JSON.stringify(input.decisions ?? null),
5921
- JSON.stringify(input.actions_taken ?? null),
5959
+ input.decisions ? JSON.stringify(input.decisions) : null,
5960
+ input.actions_taken ? JSON.stringify(input.actions_taken) : null,
5922
5961
  created_at
5923
5962
  );
5924
5963
  return {
@@ -7239,7 +7278,7 @@ function registerTaskTools(server, runtime) {
7239
7278
  ]).nullable().optional(),
7240
7279
  source_ref: z7.string().nullable().optional(),
7241
7280
  expected_effort: z7.enum(["XS", "S", "M", "L", "XL"]).nullable().optional(),
7242
- agent_id: z7.string()
7281
+ agent_id: z7.string().default("orchestrator")
7243
7282
  },
7244
7283
  (input) => ({
7245
7284
  task: runtime.create_task(
@@ -7439,11 +7478,21 @@ function registerTaskTools(server, runtime) {
7439
7478
  registerTool(
7440
7479
  server,
7441
7480
  "dashboard",
7442
- "Get project dashboard including goal progress rollups.",
7481
+ "Get project dashboard including goal progress rollups. Defaults to the first project if project_id is omitted.",
7443
7482
  {
7444
- project_id: z7.string()
7483
+ project_id: z7.string().optional()
7445
7484
  },
7446
- (input) => runtime.dashboard({ project_id: String(input.project_id) })
7485
+ (input) => {
7486
+ let projectId = input.project_id;
7487
+ if (!projectId) {
7488
+ const { projects } = runtime.list_projects();
7489
+ if (projects.length === 0) {
7490
+ return { success: false, error: "no projects found" };
7491
+ }
7492
+ projectId = projects[0].id;
7493
+ }
7494
+ return runtime.dashboard({ project_id: projectId });
7495
+ }
7447
7496
  );
7448
7497
  registerTool(
7449
7498
  server,
@@ -7866,7 +7915,7 @@ function registerTaskTools(server, runtime) {
7866
7915
  ).optional(),
7867
7916
  source_ref: z7.string().optional(),
7868
7917
  priority: z7.enum(["critical", "high", "medium", "low"]).default("medium"),
7869
- agent_id: z7.string()
7918
+ agent_id: z7.string().default("orchestrator")
7870
7919
  },
7871
7920
  (input) => runtime.create_goal(input)
7872
7921
  );
@@ -7906,11 +7955,48 @@ function registerTaskTools(server, runtime) {
7906
7955
  registerTool(
7907
7956
  server,
7908
7957
  "get_execution_view",
7909
- "Get execution view (ready/in_progress/blocked/done and dependency edges).",
7958
+ "Get execution view (ready/in_progress/blocked/done and dependency edges) for a goal or all goals in a project.",
7910
7959
  {
7911
- goal_id: z7.string()
7960
+ goal_id: z7.string().optional(),
7961
+ project_id: z7.string().optional()
7912
7962
  },
7913
- (input) => runtime.get_execution_view(input)
7963
+ (input) => {
7964
+ const goalId = input.goal_id;
7965
+ const projectId = input.project_id;
7966
+ if (!goalId && !projectId) {
7967
+ return { success: false, error: "goal_id or project_id is required" };
7968
+ }
7969
+ if (goalId) {
7970
+ return runtime.get_execution_view({ goal_id: goalId });
7971
+ }
7972
+ const dashboardResult = runtime.dashboard({ project_id: projectId });
7973
+ const goalIds = dashboardResult.goals.map((g) => g.goal_id);
7974
+ if (goalIds.length === 0) {
7975
+ return {
7976
+ ready: [],
7977
+ in_progress: [],
7978
+ blocked: [],
7979
+ done: [],
7980
+ dependency_edges: []
7981
+ };
7982
+ }
7983
+ const merged = {
7984
+ ready: [],
7985
+ in_progress: [],
7986
+ blocked: [],
7987
+ done: [],
7988
+ dependency_edges: []
7989
+ };
7990
+ for (const gid of goalIds) {
7991
+ const view = runtime.get_execution_view({ goal_id: gid });
7992
+ merged.ready.push(...view.ready);
7993
+ merged.in_progress.push(...view.in_progress);
7994
+ merged.blocked.push(...view.blocked);
7995
+ merged.done.push(...view.done);
7996
+ merged.dependency_edges.push(...view.dependency_edges);
7997
+ }
7998
+ return merged;
7999
+ }
7914
8000
  );
7915
8001
  }
7916
8002
  var acceptanceCriteriaSchema;
@@ -8242,6 +8328,16 @@ var init_server = __esm({
8242
8328
  const runtime = this.tasksRuntime;
8243
8329
  this.taskLifecycleManager = {
8244
8330
  createAndStartTask(params) {
8331
+ let createdBy = "orchestrator";
8332
+ if (params.parent_task_id) {
8333
+ try {
8334
+ const parentResult = runtime.get_task(params.parent_task_id, false);
8335
+ if (parentResult.task.assignee) {
8336
+ createdBy = parentResult.task.assignee;
8337
+ }
8338
+ } catch {
8339
+ }
8340
+ }
8245
8341
  const task = runtime.create_task({
8246
8342
  title: params.title,
8247
8343
  project_id: params.project_id,
@@ -8250,7 +8346,7 @@ var init_server = __esm({
8250
8346
  priority: params.priority,
8251
8347
  expected_effort: params.expected_effort,
8252
8348
  description: params.description
8253
- }, params.agent);
8349
+ }, createdBy);
8254
8350
  runtime.claim_and_start({
8255
8351
  task_id: task.id,
8256
8352
  agent_id: params.agent
@@ -8307,7 +8403,7 @@ var init_server = __esm({
8307
8403
  this.agentEventStore
8308
8404
  );
8309
8405
  this.server = new McpServer(
8310
- { name: "agentic-relay", version: "2.0.1" },
8406
+ { name: "agentic-relay", version: "2.0.2" },
8311
8407
  createMcpServerOptions()
8312
8408
  );
8313
8409
  this.registerTools(this.server);
@@ -8793,7 +8889,7 @@ var init_server = __esm({
8793
8889
  sessionIdGenerator: () => randomUUID()
8794
8890
  });
8795
8891
  const server = new McpServer(
8796
- { name: "agentic-relay", version: "2.0.1" },
8892
+ { name: "agentic-relay", version: "2.0.2" },
8797
8893
  createMcpServerOptions()
8798
8894
  );
8799
8895
  this.registerTools(server);
@@ -13233,7 +13329,7 @@ function createMCPCommand(configManager2, registry2, sessionManager2, hooksEngin
13233
13329
  responseOutputDir,
13234
13330
  relayConfig
13235
13331
  );
13236
- await server.start({ transport, port, currentVersion: "2.0.1" });
13332
+ await server.start({ transport, port, currentVersion: "2.0.2" });
13237
13333
  }
13238
13334
  })
13239
13335
  },
@@ -13393,7 +13489,7 @@ function createVersionCommand(registry2) {
13393
13489
  description: "Show relay and backend versions"
13394
13490
  },
13395
13491
  async run() {
13396
- const relayVersion = "2.0.1";
13492
+ const relayVersion = "2.0.2";
13397
13493
  console.log(`agentic-relay v${relayVersion}`);
13398
13494
  console.log("");
13399
13495
  console.log("Backends:");
@@ -13790,7 +13886,7 @@ var subCommandNames = /* @__PURE__ */ new Set(["claude", "codex", "gemini", "upd
13790
13886
  var main = defineCommand11({
13791
13887
  meta: {
13792
13888
  name: "relay",
13793
- version: "2.0.1",
13889
+ version: "2.0.2",
13794
13890
  description: "Unified CLI proxy for Claude Code, Codex CLI, and Gemini CLI"
13795
13891
  },
13796
13892
  args: {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@rk0429/agentic-relay",
3
- "version": "2.0.1",
3
+ "version": "2.0.2",
4
4
  "description": "Unified CLI proxy for Claude Code, Codex CLI, and Gemini CLI with MCP-based multi-layer sub-agent orchestration",
5
5
  "type": "module",
6
6
  "license": "Apache-2.0",