@rk0429/agentic-relay 2.0.1 → 2.0.3

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 +134 -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);
@@ -5144,6 +5183,9 @@ var init_tasks_runtime = __esm({
5144
5183
  const skip_review = task.metadata?.skip_review === true;
5145
5184
  const nextStatus = skip_review ? "done" : "review";
5146
5185
  if (nextStatus === "done") {
5186
+ if (requiredGateCount > 0) {
5187
+ this.qualityGateManager.assert_review_to_done_allowed(task.id, input.agent_id);
5188
+ }
5147
5189
  this.ensureChildTasksDone(task.id);
5148
5190
  }
5149
5191
  const lock = this.lockManager.get_lock(task.id);
@@ -5917,8 +5959,8 @@ var init_tasks_runtime = __esm({
5917
5959
  input.project_id,
5918
5960
  input.trigger_type,
5919
5961
  JSON.stringify(input.assessment),
5920
- JSON.stringify(input.decisions ?? null),
5921
- JSON.stringify(input.actions_taken ?? null),
5962
+ input.decisions ? JSON.stringify(input.decisions) : null,
5963
+ input.actions_taken ? JSON.stringify(input.actions_taken) : null,
5922
5964
  created_at
5923
5965
  );
5924
5966
  return {
@@ -7239,7 +7281,7 @@ function registerTaskTools(server, runtime) {
7239
7281
  ]).nullable().optional(),
7240
7282
  source_ref: z7.string().nullable().optional(),
7241
7283
  expected_effort: z7.enum(["XS", "S", "M", "L", "XL"]).nullable().optional(),
7242
- agent_id: z7.string()
7284
+ agent_id: z7.string().default("orchestrator")
7243
7285
  },
7244
7286
  (input) => ({
7245
7287
  task: runtime.create_task(
@@ -7439,11 +7481,21 @@ function registerTaskTools(server, runtime) {
7439
7481
  registerTool(
7440
7482
  server,
7441
7483
  "dashboard",
7442
- "Get project dashboard including goal progress rollups.",
7484
+ "Get project dashboard including goal progress rollups. Defaults to the first project if project_id is omitted.",
7443
7485
  {
7444
- project_id: z7.string()
7486
+ project_id: z7.string().optional()
7445
7487
  },
7446
- (input) => runtime.dashboard({ project_id: String(input.project_id) })
7488
+ (input) => {
7489
+ let projectId = input.project_id;
7490
+ if (!projectId) {
7491
+ const { projects } = runtime.list_projects();
7492
+ if (projects.length === 0) {
7493
+ return { success: false, error: "no projects found" };
7494
+ }
7495
+ projectId = projects[0].id;
7496
+ }
7497
+ return runtime.dashboard({ project_id: projectId });
7498
+ }
7447
7499
  );
7448
7500
  registerTool(
7449
7501
  server,
@@ -7866,7 +7918,7 @@ function registerTaskTools(server, runtime) {
7866
7918
  ).optional(),
7867
7919
  source_ref: z7.string().optional(),
7868
7920
  priority: z7.enum(["critical", "high", "medium", "low"]).default("medium"),
7869
- agent_id: z7.string()
7921
+ agent_id: z7.string().default("orchestrator")
7870
7922
  },
7871
7923
  (input) => runtime.create_goal(input)
7872
7924
  );
@@ -7906,11 +7958,48 @@ function registerTaskTools(server, runtime) {
7906
7958
  registerTool(
7907
7959
  server,
7908
7960
  "get_execution_view",
7909
- "Get execution view (ready/in_progress/blocked/done and dependency edges).",
7961
+ "Get execution view (ready/in_progress/blocked/done and dependency edges) for a goal or all goals in a project.",
7910
7962
  {
7911
- goal_id: z7.string()
7963
+ goal_id: z7.string().optional(),
7964
+ project_id: z7.string().optional()
7912
7965
  },
7913
- (input) => runtime.get_execution_view(input)
7966
+ (input) => {
7967
+ const goalId = input.goal_id;
7968
+ const projectId = input.project_id;
7969
+ if (!goalId && !projectId) {
7970
+ return { success: false, error: "goal_id or project_id is required" };
7971
+ }
7972
+ if (goalId) {
7973
+ return runtime.get_execution_view({ goal_id: goalId });
7974
+ }
7975
+ const dashboardResult = runtime.dashboard({ project_id: projectId });
7976
+ const goalIds = dashboardResult.goals.map((g) => g.goal_id);
7977
+ if (goalIds.length === 0) {
7978
+ return {
7979
+ ready: [],
7980
+ in_progress: [],
7981
+ blocked: [],
7982
+ done: [],
7983
+ dependency_edges: []
7984
+ };
7985
+ }
7986
+ const merged = {
7987
+ ready: [],
7988
+ in_progress: [],
7989
+ blocked: [],
7990
+ done: [],
7991
+ dependency_edges: []
7992
+ };
7993
+ for (const gid of goalIds) {
7994
+ const view = runtime.get_execution_view({ goal_id: gid });
7995
+ merged.ready.push(...view.ready);
7996
+ merged.in_progress.push(...view.in_progress);
7997
+ merged.blocked.push(...view.blocked);
7998
+ merged.done.push(...view.done);
7999
+ merged.dependency_edges.push(...view.dependency_edges);
8000
+ }
8001
+ return merged;
8002
+ }
7914
8003
  );
7915
8004
  }
7916
8005
  var acceptanceCriteriaSchema;
@@ -8242,6 +8331,16 @@ var init_server = __esm({
8242
8331
  const runtime = this.tasksRuntime;
8243
8332
  this.taskLifecycleManager = {
8244
8333
  createAndStartTask(params) {
8334
+ let createdBy = "orchestrator";
8335
+ if (params.parent_task_id) {
8336
+ try {
8337
+ const parentResult = runtime.get_task(params.parent_task_id, false);
8338
+ if (parentResult.task.assignee) {
8339
+ createdBy = parentResult.task.assignee;
8340
+ }
8341
+ } catch {
8342
+ }
8343
+ }
8245
8344
  const task = runtime.create_task({
8246
8345
  title: params.title,
8247
8346
  project_id: params.project_id,
@@ -8250,7 +8349,7 @@ var init_server = __esm({
8250
8349
  priority: params.priority,
8251
8350
  expected_effort: params.expected_effort,
8252
8351
  description: params.description
8253
- }, params.agent);
8352
+ }, createdBy);
8254
8353
  runtime.claim_and_start({
8255
8354
  task_id: task.id,
8256
8355
  agent_id: params.agent
@@ -8307,7 +8406,7 @@ var init_server = __esm({
8307
8406
  this.agentEventStore
8308
8407
  );
8309
8408
  this.server = new McpServer(
8310
- { name: "agentic-relay", version: "2.0.1" },
8409
+ { name: "agentic-relay", version: "2.0.3" },
8311
8410
  createMcpServerOptions()
8312
8411
  );
8313
8412
  this.registerTools(this.server);
@@ -8793,7 +8892,7 @@ var init_server = __esm({
8793
8892
  sessionIdGenerator: () => randomUUID()
8794
8893
  });
8795
8894
  const server = new McpServer(
8796
- { name: "agentic-relay", version: "2.0.1" },
8895
+ { name: "agentic-relay", version: "2.0.3" },
8797
8896
  createMcpServerOptions()
8798
8897
  );
8799
8898
  this.registerTools(server);
@@ -13233,7 +13332,7 @@ function createMCPCommand(configManager2, registry2, sessionManager2, hooksEngin
13233
13332
  responseOutputDir,
13234
13333
  relayConfig
13235
13334
  );
13236
- await server.start({ transport, port, currentVersion: "2.0.1" });
13335
+ await server.start({ transport, port, currentVersion: "2.0.3" });
13237
13336
  }
13238
13337
  })
13239
13338
  },
@@ -13393,7 +13492,7 @@ function createVersionCommand(registry2) {
13393
13492
  description: "Show relay and backend versions"
13394
13493
  },
13395
13494
  async run() {
13396
- const relayVersion = "2.0.1";
13495
+ const relayVersion = "2.0.3";
13397
13496
  console.log(`agentic-relay v${relayVersion}`);
13398
13497
  console.log("");
13399
13498
  console.log("Backends:");
@@ -13790,7 +13889,7 @@ var subCommandNames = /* @__PURE__ */ new Set(["claude", "codex", "gemini", "upd
13790
13889
  var main = defineCommand11({
13791
13890
  meta: {
13792
13891
  name: "relay",
13793
- version: "2.0.1",
13892
+ version: "2.0.3",
13794
13893
  description: "Unified CLI proxy for Claude Code, Codex CLI, and Gemini CLI"
13795
13894
  },
13796
13895
  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.3",
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",