@arcships/morula-runtime 0.1.0-alpha.13 → 0.1.0-alpha.14
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/index.js +41 -16
- package/dist/morula.js +2 -2
- package/dist/plugin/plugin.json +1 -1
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -740,7 +740,7 @@ var BUILD_ID, BUILD_CONTEXTS, BUILD_DEFAULT_CONTEXT;
|
|
|
740
740
|
var init_build_env = __esm({
|
|
741
741
|
"../morula-cli-core/dist/build-env.js"() {
|
|
742
742
|
"use strict";
|
|
743
|
-
BUILD_ID = "
|
|
743
|
+
BUILD_ID = "20260923140226.31d77ab2";
|
|
744
744
|
BUILD_CONTEXTS = {
|
|
745
745
|
"local": "http://localhost:8080/api",
|
|
746
746
|
"test": "https://morula.basecastle.com/api",
|
|
@@ -4424,7 +4424,7 @@ init_dist2();
|
|
|
4424
4424
|
init_dist2();
|
|
4425
4425
|
|
|
4426
4426
|
// src/build-env.ts
|
|
4427
|
-
var BUILD_VERSION2 = "0.1.0-alpha.
|
|
4427
|
+
var BUILD_VERSION2 = "0.1.0-alpha.14";
|
|
4428
4428
|
|
|
4429
4429
|
// src/commands/daemon.ts
|
|
4430
4430
|
init_dist();
|
|
@@ -8677,7 +8677,6 @@ var SessionHost = class {
|
|
|
8677
8677
|
env,
|
|
8678
8678
|
turnNo: 0,
|
|
8679
8679
|
promptInFlight: null,
|
|
8680
|
-
cancelRequested: false,
|
|
8681
8680
|
// resume 成功 → dim 会话里已有上一进程注入的管家指令,不重复前置
|
|
8682
8681
|
instructed: resumed,
|
|
8683
8682
|
appliedConfig: { ...appliedConfig, permission },
|
|
@@ -8710,7 +8709,6 @@ var SessionHost = class {
|
|
|
8710
8709
|
if (!cmd.prompt?.trim())
|
|
8711
8710
|
return { ok: false, error: "SESSION_PROMPT_EMPTY" };
|
|
8712
8711
|
managed.turnNo += 1;
|
|
8713
|
-
managed.cancelRequested = false;
|
|
8714
8712
|
this.touch(managed);
|
|
8715
8713
|
const turnNo = managed.turnNo;
|
|
8716
8714
|
const mapper = new AcpEventMapper();
|
|
@@ -8906,12 +8904,16 @@ ${fileRefs.join("\n")}` : text }];
|
|
|
8906
8904
|
}
|
|
8907
8905
|
return { blocks, fileRefs };
|
|
8908
8906
|
}
|
|
8909
|
-
/**
|
|
8907
|
+
/**
|
|
8908
|
+
* 取消当前回合(ACP `session/cancel` 通知;会话保持打开——长驻语义)。
|
|
8909
|
+
*
|
|
8910
|
+
* **软中断**:dim 在安全点(step 之间)生效,不是硬杀进程;daemon 只负责把通知发出去,
|
|
8911
|
+
* 本轮的终态仍由 ACP `session/prompt` 响应驱动(`cancelled` → `turn_completed`)。
|
|
8912
|
+
*/
|
|
8910
8913
|
cancel(cmd) {
|
|
8911
8914
|
const managed = this.sessions.get(cmd.sessionId);
|
|
8912
8915
|
if (!managed)
|
|
8913
8916
|
return { ok: false, error: "SESSION_NOT_OPEN" };
|
|
8914
|
-
managed.cancelRequested = true;
|
|
8915
8917
|
managed.conn.cancel(managed.dimSessionId);
|
|
8916
8918
|
this.touch(managed);
|
|
8917
8919
|
return { ok: true };
|
|
@@ -10107,16 +10109,25 @@ var DaemonRunner = class {
|
|
|
10107
10109
|
/**
|
|
10108
10110
|
* 会话宿主命令分发。
|
|
10109
10111
|
*
|
|
10110
|
-
*
|
|
10112
|
+
* 三道闸:
|
|
10111
10113
|
* ① **runtimeId + daemonId 自过滤**(tenant 广播 → 只有归属设备处理;字段缺失时不过滤,兼容旧服务端)。
|
|
10112
10114
|
* daemonId 是**实例**维度(issues/duplicate-daemon-same-runtime-double-execution.md):同机多实例
|
|
10113
10115
|
* 注册时会复用同一行 AgentRuntime(同一 runtimeId),缺了它两个实例会各自 `open` 同一 sessionId
|
|
10114
10116
|
* 并各跑一轮 prompt(实测:同一轮两份正文事件、两个 daemon 都「会话已打开」);
|
|
10115
|
-
* ②
|
|
10116
|
-
*
|
|
10117
|
-
* prompt 可能先于 open 完成而拿到 SESSION_NOT_OPEN。故按 sessionId 串成一条 promise 链。
|
|
10117
|
+
* ② **按会话串行**(open / prompt / config):服务端每轮 prompt 前会补发 `open` 做兜底,而 socket.io
|
|
10118
|
+
* 只保证「送达有序」,不保证「异步处理有序」——`void handleSessionCommand()` 会让 open/prompt
|
|
10119
|
+
* 交错执行,prompt 可能先于 open 完成而拿到 SESSION_NOT_OPEN。故按 sessionId 串成一条 promise 链。
|
|
10120
|
+
* ③ **抢占类命令(cancel / close)不进链**:`prompt` 的 promise 直到本轮 `end_turn` 才 resolve
|
|
10121
|
+
* (`session-host.prompt()` await 的是 ACP `session/prompt` 响应),排在它后面 = 取消永远发生在
|
|
10122
|
+
* 回合结束之后,用户看到的是「点了停止但没停」(issues/steward-session-cancel-queued-behind-prompt.md)。
|
|
10123
|
+
* 它们只等该会话的 **open 门**——open 未完成时会话还不存在,取消只会拿到 SESSION_NOT_OPEN。
|
|
10118
10124
|
*/
|
|
10119
10125
|
sessionCommandChains = /* @__PURE__ */ new Map();
|
|
10126
|
+
/**
|
|
10127
|
+
* 各会话**在飞 `open` 命令**的完成信号(抢占类命令的唯一前置门)。
|
|
10128
|
+
* 只在 open 入链时登记,open 落定即清理——它表达的是「会话在设备上就绪」,与后续 prompt 无关。
|
|
10129
|
+
*/
|
|
10130
|
+
sessionOpenGates = /* @__PURE__ */ new Map();
|
|
10120
10131
|
handleSessionCommand(kind, payload) {
|
|
10121
10132
|
const runtimeId = typeof payload.runtimeId === "string" ? payload.runtimeId : void 0;
|
|
10122
10133
|
if (runtimeId && this.runtimeId && runtimeId !== this.runtimeId)
|
|
@@ -10129,15 +10140,25 @@ var DaemonRunner = class {
|
|
|
10129
10140
|
this.log(`[daemon] \u4F1A\u8BDD\u547D\u4EE4 ${kind} \u7F3A\u5C11 sessionId\uFF08\u5FFD\u7565\uFF09`);
|
|
10130
10141
|
return Promise.resolve();
|
|
10131
10142
|
}
|
|
10143
|
+
const logFailure = (err) => {
|
|
10144
|
+
this.log(`[daemon] \u4F1A\u8BDD\u547D\u4EE4 ${kind} \u6267\u884C\u5931\u8D25: ${err instanceof Error ? err.message : String(err)}`);
|
|
10145
|
+
};
|
|
10146
|
+
if (kind === "cancel" || kind === "close") {
|
|
10147
|
+
const gate = this.sessionOpenGates.get(sessionId) ?? Promise.resolve();
|
|
10148
|
+
return gate.catch(() => {
|
|
10149
|
+
}).then(() => this.runSessionCommand(kind, payload)).catch(logFailure);
|
|
10150
|
+
}
|
|
10132
10151
|
const prev = this.sessionCommandChains.get(sessionId) ?? Promise.resolve();
|
|
10133
10152
|
const next = prev.catch(() => {
|
|
10134
|
-
}).then(() => this.runSessionCommand(kind, payload)).catch(
|
|
10135
|
-
this.log(`[daemon] \u4F1A\u8BDD\u547D\u4EE4 ${kind} \u6267\u884C\u5931\u8D25: ${err instanceof Error ? err.message : String(err)}`);
|
|
10136
|
-
});
|
|
10153
|
+
}).then(() => this.runSessionCommand(kind, payload)).catch(logFailure);
|
|
10137
10154
|
this.sessionCommandChains.set(sessionId, next);
|
|
10155
|
+
if (kind === "open")
|
|
10156
|
+
this.sessionOpenGates.set(sessionId, next);
|
|
10138
10157
|
void next.finally(() => {
|
|
10139
10158
|
if (this.sessionCommandChains.get(sessionId) === next)
|
|
10140
10159
|
this.sessionCommandChains.delete(sessionId);
|
|
10160
|
+
if (this.sessionOpenGates.get(sessionId) === next)
|
|
10161
|
+
this.sessionOpenGates.delete(sessionId);
|
|
10141
10162
|
});
|
|
10142
10163
|
return next;
|
|
10143
10164
|
}
|
|
@@ -10153,9 +10174,13 @@ var DaemonRunner = class {
|
|
|
10153
10174
|
await host.open(payload);
|
|
10154
10175
|
else if (kind === "prompt")
|
|
10155
10176
|
await host.prompt(payload);
|
|
10156
|
-
else if (kind === "cancel")
|
|
10157
|
-
host.cancel(payload);
|
|
10158
|
-
|
|
10177
|
+
else if (kind === "cancel") {
|
|
10178
|
+
const res = host.cancel(payload);
|
|
10179
|
+
if (res.ok)
|
|
10180
|
+
this.log(`[daemon] \u4F1A\u8BDD ${String(payload.sessionId ?? "")} \u53D6\u6D88\u5DF2\u4E0B\u53D1\uFF08ACP session/cancel\uFF09`);
|
|
10181
|
+
else
|
|
10182
|
+
this.log(`[daemon] \u4F1A\u8BDD ${String(payload.sessionId ?? "")} \u53D6\u6D88\u5931\u8D25: ${res.error ?? "UNKNOWN"}`);
|
|
10183
|
+
} else if (kind === "config")
|
|
10159
10184
|
await host.config(payload);
|
|
10160
10185
|
else if (kind === "close")
|
|
10161
10186
|
await host.close(payload);
|
package/dist/morula.js
CHANGED
|
@@ -704,8 +704,8 @@ function page(ok, message) {
|
|
|
704
704
|
}
|
|
705
705
|
|
|
706
706
|
// ../morula-cli-core/dist/build-env.js
|
|
707
|
-
var BUILD_VERSION = "0.1.0-alpha.
|
|
708
|
-
var BUILD_ID = "
|
|
707
|
+
var BUILD_VERSION = "0.1.0-alpha.14";
|
|
708
|
+
var BUILD_ID = "20260923140226.31d77ab2";
|
|
709
709
|
var BUILD_CONTEXTS = {
|
|
710
710
|
"local": "http://localhost:8080/api",
|
|
711
711
|
"test": "https://morula.basecastle.com/api",
|
package/dist/plugin/plugin.json
CHANGED
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@arcships/morula-runtime",
|
|
3
3
|
"type": "module",
|
|
4
|
-
"version": "0.1.0-alpha.
|
|
4
|
+
"version": "0.1.0-alpha.14",
|
|
5
5
|
"description": "Device-level CLI for the Morula local agent runtime (daemon/portal/models/auth) and the Morula business CLI (morula), distributed via npm",
|
|
6
6
|
"bin": {
|
|
7
7
|
"morula-runtime": "./bin/morula-runtime.js",
|