@michengai/dsh-automation 0.1.4 → 0.1.6

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/lib/index.js CHANGED
@@ -21801,6 +21801,9 @@ function unattendedToolGuardReason(name2, args) {
21801
21801
  }
21802
21802
  return UNATTENDED_TOOL_ALLOWLIST.has(name2) ? void 0 : `\u5DE5\u5177 '${name2}' \u4E0D\u5728\u65E0\u4EBA\u503C\u5B88\u81EA\u52A8\u5316\u5141\u8BB8\u5217\u8868\u4E2D\u3002`;
21803
21803
  }
21804
+ function sandboxModeForPermission(permission) {
21805
+ return permission === "full-access" ? "danger-full-access" : permission;
21806
+ }
21804
21807
  function summarizeRun(events, firstSeq) {
21805
21808
  let started = false;
21806
21809
  let text = "";
@@ -21870,7 +21873,7 @@ async function executeAutomationRun(ctx, definition, run, config2) {
21870
21873
  installModelSelection(agentCtx, { current: selection, assembled: void 0 });
21871
21874
  const agent = agentCtx.agent;
21872
21875
  if (agent === void 0) throw new Error("automation setup has no scoped Agent");
21873
- if (target.permissionPreset !== "full-access") setSandboxMode(agent.session, target.permissionPreset);
21876
+ setSandboxMode(agent.session, sandboxModeForPermission(target.permissionPreset));
21874
21877
  setApprovalPolicy(agent.session, "never");
21875
21878
  agentCtx.tools.guard((exec) => unattendedToolGuardReason(exec.name, exec.arguments));
21876
21879
  }
@@ -22008,6 +22011,7 @@ var AutomationService = class _AutomationService {
22008
22011
  service.definitions = domain2.table("definitions");
22009
22012
  service.runs = domain2.table("runs");
22010
22013
  await service.recoverInterruptedRuns();
22014
+ await service.reconcileMissingSessions();
22011
22015
  await service.pruneAllHistory();
22012
22016
  return service;
22013
22017
  } catch (error51) {
@@ -22167,6 +22171,32 @@ var AutomationService = class _AutomationService {
22167
22171
  }
22168
22172
  });
22169
22173
  }
22174
+ async reconcileMissingSessions() {
22175
+ const known = await this.knownSessionIds();
22176
+ if (known === void 0) return;
22177
+ await this.serialize(async () => {
22178
+ for (const [runId, run] of this.runs.entries()) {
22179
+ if (typeof run.sessionId !== "string" || run.sessionId === "") continue;
22180
+ if (known.has(run.sessionId)) continue;
22181
+ await this.runs.put(runId, { ...run, sessionId: null });
22182
+ }
22183
+ });
22184
+ }
22185
+ async knownSessionIds() {
22186
+ const live = this.ctx.sessions;
22187
+ const persistence = this.ctx.get?.("sessionPersistence");
22188
+ const canListLive = typeof live?.list === "function";
22189
+ const canListStored = typeof persistence?.list === "function";
22190
+ if (!canListLive && !canListStored) return void 0;
22191
+ const ids = /* @__PURE__ */ new Set();
22192
+ if (canListLive && live?.list !== void 0) {
22193
+ for (const session of live.list()) ids.add(String(session.id));
22194
+ }
22195
+ if (canListStored && persistence?.list !== void 0) {
22196
+ for (const header of await persistence.list()) ids.add(String(header.id));
22197
+ }
22198
+ return ids;
22199
+ }
22170
22200
  async forgetAutomationSessions(automationId) {
22171
22201
  const id = automationId.trim();
22172
22202
  if (id === "") return;
@@ -22819,13 +22849,15 @@ async function apply(ctx, rawConfig) {
22819
22849
  };
22820
22850
  let stopPrompt = () => {
22821
22851
  };
22852
+ let stopSessionGone = () => {
22853
+ };
22822
22854
  let removeRpc = async () => {
22823
22855
  };
22824
22856
  const cleanup = async () => {
22825
22857
  if (cleaned) return;
22826
22858
  cleaned = true;
22827
22859
  alive = false;
22828
- for (const stop of [stopCreated, stopDisposed, stopApproval, stopPrompt]) {
22860
+ for (const stop of [stopCreated, stopDisposed, stopApproval, stopPrompt, stopSessionGone]) {
22829
22861
  try {
22830
22862
  stop();
22831
22863
  } catch (error51) {
@@ -22861,6 +22893,11 @@ async function apply(ctx, rawConfig) {
22861
22893
  stopDisposed = ctx.on("agent/disposed", ({ agent }) => {
22862
22894
  agentTools.delete(agent);
22863
22895
  });
22896
+ stopSessionGone = ctx.on("session/disposed", (session) => {
22897
+ const id = String(session?.id ?? "");
22898
+ if (id === "") return;
22899
+ void service.forgetSession(id);
22900
+ });
22864
22901
  const systemPrompt = ctx.get("systemPrompt");
22865
22902
  if (typeof systemPrompt?.section === "function") {
22866
22903
  stopPrompt = systemPrompt.section({
@@ -1,5 +1,8 @@
1
+ import type { AutomationPermission } from './protocol.js';
1
2
  /** 新建/编辑弹窗只允许取消或 ESC 关闭,点旁边不能关。 */
2
3
  export declare function shouldCloseCreateModal(reason: 'backdrop' | 'escape' | 'cancel'): boolean;
4
+ /** 只有从非完全访问切换到完全访问时才需要风险确认。 */
5
+ export declare function shouldConfirmFullAccess(current: AutomationPermission, next: AutomationPermission): boolean;
3
6
  /** 和 Chat 一样:先选目录,取消则不登记;没有手输路径这条路。 */
4
7
  export declare function adoptPickedWorkspace(input: {
5
8
  readonly pick: () => Promise<string | null>;
@@ -139,6 +139,11 @@ export declare const en: {
139
139
  readonly 'form.workspaceWrite': "Workspace Write";
140
140
  readonly 'form.fullAccess': "Full access";
141
141
  readonly 'form.workspaceWriteHint': "May change files in this workspace; past approvals are not reused.";
142
+ readonly 'access.confirm.title': "Enable Full access?";
143
+ readonly 'access.confirm.description': "Full access reduces confirmation steps and allows the Agent to directly perform more operations, including sensitive operations, file changes, or external commands. Use it only when you trust this task.";
144
+ readonly 'access.confirm.acknowledge': "I understand the risks and want to continue";
145
+ readonly 'access.confirm.cancel': "Cancel";
146
+ readonly 'access.confirm.enable': "Enable Full access";
142
147
  readonly 'form.cancel': "Cancel";
143
148
  readonly 'form.submit': "Create automation";
144
149
  readonly 'form.submitting': "Creating…";
@@ -44,6 +44,8 @@ export declare function groupScheduledSessions(automations: readonly {
44
44
  readonly id: string;
45
45
  readonly name: string;
46
46
  }[], runs: readonly ScheduleRunLike[]): ScheduleRailGroup[];
47
+ /** 归档中的、以及宿主已经不认识的 Session,都不应再出现在定时页。 */
48
+ export declare function keepScheduledSessionLink(sessionId: string | undefined, archived: ReadonlySet<string>, presentIds?: ReadonlySet<string>): boolean;
47
49
  export declare function collectScheduledSessionIds(runs: readonly {
48
50
  readonly sessionId?: string | null;
49
51
  }[] | undefined): Set<string>;
@@ -21,6 +21,8 @@ export interface ExecutorConfig {
21
21
  readonly sessionId: string;
22
22
  readonly signal?: AbortSignal;
23
23
  }
24
+ /** 自动化权限名称与 DSH 沙箱事件名称不同,必须在写入会话前转换。 */
25
+ export declare function sandboxModeForPermission(permission: AutomationDefinition['permissionPreset']): 'read-only' | 'workspace-write' | 'danger-full-access';
24
26
  export declare function summarizeRun(events: readonly SessionEventLike[], firstSeq: number): {
25
27
  readonly text: string;
26
28
  readonly reason?: Record<string, any>;
@@ -86,6 +86,8 @@ export declare class AutomationService {
86
86
  runNow(scope: AutomationScope, id: string, signal?: AbortSignal): Promise<AutomationRun>;
87
87
  markRead(scope: AutomationScope, runId: string, signal?: AbortSignal): Promise<AutomationRun>;
88
88
  forgetSession(sessionId: string): Promise<void>;
89
+ reconcileMissingSessions(): Promise<void>;
90
+ private knownSessionIds;
89
91
  forgetAutomationSessions(automationId: string): Promise<void>;
90
92
  adoptSession(sessionId: string): Promise<void>;
91
93
  addWorkspace(path: string): Promise<WorkspaceOption>;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@michengai/dsh-automation",
3
- "version": "0.1.4",
3
+ "version": "0.1.6",
4
4
  "description": "在独立 DSH Session 中按计划执行编码任务,支持 Web 设置页与 Agent 双入口管理。",
5
5
  "type": "module",
6
6
  "main": "./lib/index.js",
@@ -18,7 +18,7 @@
18
18
  },
19
19
  "files": [
20
20
  "lib",
21
- "assets",
21
+ "assets",
22
22
  "docs",
23
23
  "cordis.patch.yml",
24
24
  "README.md",
@@ -110,4 +110,4 @@
110
110
  "registry": "https://registry.npmjs.org/"
111
111
  }
112
112
  }
113
-
113
+