@yachiyo-5i/xlyra-agent 1.3.0 → 1.3.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/cli.cjs CHANGED
@@ -642,6 +642,7 @@ var EscalationRequiredError = class extends Error {
642
642
  };
643
643
  var EscalationGrants = class {
644
644
  grants = /* @__PURE__ */ new Map();
645
+ oneShotGrants = /* @__PURE__ */ new Map();
645
646
  /** 会话级完全访问开关(前端 permission_mode=full 注入;ask 时撤销,不随消息残留) */
646
647
  fullAccess = /* @__PURE__ */ new Set();
647
648
  /** 完全访问模式:跳过一切路径与能力提权检查(用户已在 UI 二次确认) */
@@ -666,24 +667,48 @@ var EscalationGrants = class {
666
667
  grantCapability(sessionId, capability) {
667
668
  this.grant(sessionId, capability);
668
669
  }
670
+ grantOnce(sessionId, resolvedPath) {
671
+ let set = this.oneShotGrants.get(sessionId);
672
+ if (!set) {
673
+ set = /* @__PURE__ */ new Set();
674
+ this.oneShotGrants.set(sessionId, set);
675
+ }
676
+ set.add(resolvedPath);
677
+ }
678
+ grantCapabilityOnce(sessionId, capability) {
679
+ this.grantOnce(sessionId, capability);
680
+ }
669
681
  /** 已授权路径或其子路径视为已放开;完全访问模式直接放行 */
670
682
  isGranted(sessionId, resolvedPath) {
671
683
  if (this.fullAccess.has(sessionId)) return true;
672
684
  const set = this.grants.get(sessionId);
673
- if (!set) return false;
674
- for (const prefix of set) {
675
- const relative = import_node_path3.default.relative(prefix, resolvedPath);
676
- if (relative === "" || !relative.startsWith("..") && !import_node_path3.default.isAbsolute(relative)) return true;
685
+ if (set) {
686
+ for (const prefix of set) {
687
+ const relative = import_node_path3.default.relative(prefix, resolvedPath);
688
+ if (relative === "" || !relative.startsWith("..") && !import_node_path3.default.isAbsolute(relative)) return true;
689
+ }
690
+ }
691
+ const oneShot = this.oneShotGrants.get(sessionId);
692
+ if (oneShot?.has(resolvedPath)) {
693
+ oneShot.delete(resolvedPath);
694
+ if (oneShot.size === 0) this.oneShotGrants.delete(sessionId);
695
+ return true;
677
696
  }
678
697
  return false;
679
698
  }
680
699
  isCapabilityGranted(sessionId, capability) {
681
700
  if (this.fullAccess.has(sessionId)) return true;
682
- return this.grants.get(sessionId)?.has(capability) ?? false;
701
+ if (this.grants.get(sessionId)?.has(capability)) return true;
702
+ const oneShot = this.oneShotGrants.get(sessionId);
703
+ if (!oneShot?.has(capability)) return false;
704
+ oneShot.delete(capability);
705
+ if (oneShot.size === 0) this.oneShotGrants.delete(sessionId);
706
+ return true;
683
707
  }
684
708
  /** 会话删除时清掉授权(授权随会话生命周期) */
685
709
  drop(sessionId) {
686
710
  this.grants.delete(sessionId);
711
+ this.oneShotGrants.delete(sessionId);
687
712
  this.fullAccess.delete(sessionId);
688
713
  }
689
714
  };
@@ -4287,7 +4312,14 @@ function createAgentRoutes(ctx) {
4287
4312
  }
4288
4313
  );
4289
4314
  await recorder.begin(runId);
4290
- return { sessionId: args2.sessionId, messageId, runId };
4315
+ const resolvedModel = ctx.resolver.resolve(args2.model).modelId;
4316
+ return {
4317
+ sessionId: args2.sessionId,
4318
+ messageId,
4319
+ runId,
4320
+ model: resolvedModel,
4321
+ agentInstanceId: args2.agentInstanceId ?? ctx.agentInstanceId ?? "default"
4322
+ };
4291
4323
  }
4292
4324
  app.post("/sessions", async (c) => {
4293
4325
  const payload = startPayloadSchema.parse(await c.req.json());
@@ -4314,7 +4346,7 @@ function createAgentRoutes(ctx) {
4314
4346
  if (payload.permission_mode !== void 0) {
4315
4347
  ctx.grants.setFullAccess(sessionId, payload.permission_mode === "full");
4316
4348
  }
4317
- const { messageId, runId } = await launchUserMessage({
4349
+ const { messageId, runId, model, agentInstanceId } = await launchUserMessage({
4318
4350
  sessionId,
4319
4351
  content: payload.content,
4320
4352
  model: payload.model,
@@ -4326,7 +4358,7 @@ function createAgentRoutes(ctx) {
4326
4358
  },
4327
4359
  ...payload.agent_instance_id ? { agentInstanceId: payload.agent_instance_id } : {}
4328
4360
  });
4329
- return c.json(ok({ session_id: sessionId, message_id: messageId, run_id: runId }, "\u7528\u6237\u6D88\u606F\u5DF2\u63D0\u4EA4"), 202);
4361
+ return c.json(ok({ session_id: sessionId, message_id: messageId, run_id: runId, model, agent_instance_id: agentInstanceId }, "\u7528\u6237\u6D88\u606F\u5DF2\u63D0\u4EA4"), 202);
4330
4362
  });
4331
4363
  app.get("/sessions", (c) => {
4332
4364
  const limit = Math.min(Number(c.req.query("limit") ?? 50), 200);
@@ -4449,7 +4481,7 @@ function createAgentRoutes(ctx) {
4449
4481
  ctx.store.discardFromUserMessage(sessionId, payload.message_id);
4450
4482
  const history = ctx.store.buildHistory(sessionId);
4451
4483
  const remaining = ctx.store.read(sessionId).entries.length;
4452
- const { messageId, runId } = await launchUserMessage({
4484
+ const { messageId, runId, model, agentInstanceId } = await launchUserMessage({
4453
4485
  sessionId,
4454
4486
  content,
4455
4487
  model: payload.model,
@@ -4462,7 +4494,7 @@ function createAgentRoutes(ctx) {
4462
4494
  },
4463
4495
  ...payload.agent_instance_id ? { agentInstanceId: payload.agent_instance_id } : {}
4464
4496
  });
4465
- return c.json(ok({ session_id: sessionId, message_id: messageId, run_id: runId }, "\u5DF2\u91CD\u65B0\u63D0\u4EA4"), 202);
4497
+ return c.json(ok({ session_id: sessionId, message_id: messageId, run_id: runId, model, agent_instance_id: agentInstanceId }, "\u5DF2\u91CD\u65B0\u63D0\u4EA4"), 202);
4466
4498
  });
4467
4499
  app.post("/sessions/:id/grant-access", async (c) => {
4468
4500
  const sessionId = c.req.param("id");
@@ -4481,6 +4513,12 @@ function createAgentRoutes(ctx) {
4481
4513
  if (!esc || esc.type !== "escalation") fail(404, "\u63D0\u6743\u8BF7\u6C42\u4E0D\u5B58\u5728\u6216\u5DF2\u8FC7\u671F");
4482
4514
  if (esc.resolved_path !== resolved_path) fail(400, "\u6388\u6743\u8DEF\u5F84\u4E0E\u63D0\u6743\u8BF7\u6C42\u4E0D\u4E00\u81F4");
4483
4515
  if (esc.granted !== null && esc.granted !== void 0) fail(400, "\u8BE5\u63D0\u6743\u8BF7\u6C42\u5DF2\u5904\u7406\u8FC7");
4516
+ const lastModelEntry = [...entries].reverse().find(
4517
+ (entry) => isMessageEntry(entry) && Boolean(entry.model?.trim())
4518
+ );
4519
+ const model = lastModelEntry && isMessageEntry(lastModelEntry) ? lastModelEntry.model?.trim() ?? "" : "";
4520
+ if (!model) fail(400, "\u65E0\u6CD5\u786E\u5B9A\u4F1A\u8BDD\u4F7F\u7528\u7684\u6A21\u578B\uFF0C\u8BF7\u91CD\u65B0\u53D1\u9001\u6D88\u606F");
4521
+ ctx.resolver.resolve(model);
4484
4522
  ctx.store.resolveEscalation(sessionId, escalation_id, granted);
4485
4523
  if (!granted) {
4486
4524
  const history2 = ctx.store.buildHistoryBeforeEscalation(sessionId, escalation_id);
@@ -4515,37 +4553,36 @@ function createAgentRoutes(ctx) {
4515
4553
  }
4516
4554
  }
4517
4555
  }
4518
- const { runId: runId2 } = await launchUserMessage({
4556
+ const { runId: runId2, model: resumedModel2, agentInstanceId: agentInstanceId2 } = await launchUserMessage({
4519
4557
  sessionId,
4520
4558
  content: "",
4521
- model: "",
4559
+ model,
4522
4560
  history: history2,
4523
4561
  entryCount: entries.length,
4524
4562
  recordUser: false
4525
4563
  });
4526
- return c.json(ok({ session_id: sessionId, granted: false, run_id: runId2 }, "\u5DF2\u62D2\u7EDD\u6388\u6743\uFF0C\u7531\u6A21\u578B\u7EE7\u7EED\u5E94\u7B54"), 202);
4564
+ return c.json(ok({ session_id: sessionId, granted: false, run_id: runId2, model: resumedModel2, agent_instance_id: agentInstanceId2 }, "\u5DF2\u62D2\u7EDD\u6388\u6743\uFF0C\u7531\u6A21\u578B\u7EE7\u7EED\u5E94\u7B54"), 202);
4527
4565
  }
4528
4566
  if (esc.resource_type === "command") {
4529
- ctx.grants.grantCapability(sessionId, resolved_path);
4567
+ ctx.grants.grantCapabilityOnce(sessionId, resolved_path);
4530
4568
  } else {
4531
- ctx.grants.grant(sessionId, resolved_path);
4569
+ ctx.grants.grantOnce(sessionId, resolved_path);
4532
4570
  }
4533
4571
  const lastUser = [...entries].reverse().find(
4534
4572
  (e) => isMessageEntry(e) && e.message.role === "user"
4535
4573
  );
4536
4574
  if (!lastUser || !isMessageEntry(lastUser)) fail(400, "\u4F1A\u8BDD\u4E2D\u6CA1\u6709\u53EF\u7EED\u8DD1\u7684\u7528\u6237\u6D88\u606F");
4537
- ctx.resolver.resolve("");
4538
4575
  const history = ctx.store.buildHistoryBeforeEscalation(sessionId, escalation_id);
4539
- const { messageId, runId } = await launchUserMessage({
4576
+ const { messageId, runId, model: resumedModel, agentInstanceId } = await launchUserMessage({
4540
4577
  sessionId,
4541
4578
  content: "",
4542
- model: "",
4579
+ model,
4543
4580
  history,
4544
4581
  entryCount: entries.length,
4545
4582
  recordUser: false
4546
4583
  });
4547
4584
  return c.json(
4548
- ok({ session_id: sessionId, message_id: messageId, run_id: runId, granted_path: resolved_path }, "\u5DF2\u6388\u6743\u5E76\u7EE7\u7EED\u6267\u884C"),
4585
+ ok({ session_id: sessionId, message_id: messageId, run_id: runId, model: resumedModel, agent_instance_id: agentInstanceId, granted_path: resolved_path }, "\u5DF2\u6388\u6743\u5E76\u7EE7\u7EED\u6267\u884C"),
4549
4586
  202
4550
4587
  );
4551
4588
  });