@ganglion/xacpx 0.24.5-beta.0 → 0.24.6-beta.0
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/adapters/adapter-catalog.d.ts +2 -2
- package/dist/bots/bot-types.d.ts +66 -0
- package/dist/bridge/bridge-main.js +30 -4
- package/dist/bridge/engine/runtime/runtime-worker-main.js +30 -3
- package/dist/cli.js +209 -27
- package/dist/commands/session-remove-lifecycle.d.ts +9 -0
- package/dist/config/types.d.ts +1 -1
- package/dist/control/control-service.d.ts +23 -0
- package/dist/control/session-turn-runner.d.ts +2 -0
- package/dist/control/turn-queue.d.ts +8 -0
- package/dist/conversations/conversation-types.d.ts +117 -0
- package/dist/sessions/session-service.d.ts +7 -2
- package/dist/state/types.d.ts +24 -0
- package/package.json +3 -2
|
@@ -2,12 +2,12 @@ export declare const MANAGED_ADAPTERS: {
|
|
|
2
2
|
readonly codex: {
|
|
3
3
|
readonly packageName: "@agentclientprotocol/codex-acp";
|
|
4
4
|
readonly binName: "codex-acp";
|
|
5
|
-
readonly defaultVersion: "1.
|
|
5
|
+
readonly defaultVersion: "1.12.0";
|
|
6
6
|
};
|
|
7
7
|
readonly claude: {
|
|
8
8
|
readonly packageName: "@agentclientprotocol/claude-agent-acp";
|
|
9
9
|
readonly binName: "claude-agent-acp";
|
|
10
|
-
readonly defaultVersion: "0.
|
|
10
|
+
readonly defaultVersion: "0.78.0";
|
|
11
11
|
};
|
|
12
12
|
};
|
|
13
13
|
export type ManagedAdapterId = keyof typeof MANAGED_ADAPTERS;
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
export type BotRuntimeScope = "bot-direct" | "group-member" | "group-controller";
|
|
2
|
+
export interface BotProfilePresentation {
|
|
3
|
+
name: string;
|
|
4
|
+
avatar?: string;
|
|
5
|
+
role?: string;
|
|
6
|
+
}
|
|
7
|
+
export interface BotProfileBehavior {
|
|
8
|
+
instructions?: string;
|
|
9
|
+
}
|
|
10
|
+
export interface BotProfileExecution {
|
|
11
|
+
agent: string;
|
|
12
|
+
workspace: string;
|
|
13
|
+
model?: string;
|
|
14
|
+
effort?: string;
|
|
15
|
+
}
|
|
16
|
+
/** Durable linearization of the Bot fields a Run was accepted against. */
|
|
17
|
+
export interface BotProfileSnapshot {
|
|
18
|
+
revision: number;
|
|
19
|
+
capturedAt: string;
|
|
20
|
+
presentation: BotProfilePresentation;
|
|
21
|
+
behavior: BotProfileBehavior;
|
|
22
|
+
execution: BotProfileExecution;
|
|
23
|
+
}
|
|
24
|
+
export interface BotProfile {
|
|
25
|
+
id: string;
|
|
26
|
+
name: string;
|
|
27
|
+
avatar?: string;
|
|
28
|
+
role?: string;
|
|
29
|
+
instructions?: string;
|
|
30
|
+
agent: string;
|
|
31
|
+
workspace: string;
|
|
32
|
+
cwd?: string;
|
|
33
|
+
model?: string;
|
|
34
|
+
effort?: string;
|
|
35
|
+
enabled: boolean;
|
|
36
|
+
/** Monotonic Bot-config generation. Missing on PR2 records; parse defaults to 1. */
|
|
37
|
+
profileRevision: number;
|
|
38
|
+
createdAt: string;
|
|
39
|
+
updatedAt: string;
|
|
40
|
+
}
|
|
41
|
+
export declare function sessionMatchesExecution(session: {
|
|
42
|
+
agent: string;
|
|
43
|
+
workspace: string;
|
|
44
|
+
model?: string;
|
|
45
|
+
effort?: string;
|
|
46
|
+
}, execution: BotProfileExecution): boolean;
|
|
47
|
+
export declare function snapshotBotProfile(bot: BotProfile, capturedAt: string): BotProfileSnapshot;
|
|
48
|
+
interface BotRuntimeBindingBase {
|
|
49
|
+
id: string;
|
|
50
|
+
conversationId: string;
|
|
51
|
+
topicId: string;
|
|
52
|
+
logicalSessionId: string;
|
|
53
|
+
sessionAlias: string;
|
|
54
|
+
createdAt: string;
|
|
55
|
+
updatedAt: string;
|
|
56
|
+
}
|
|
57
|
+
export type BotRuntimeBinding = (BotRuntimeBindingBase & {
|
|
58
|
+
scope: "bot-direct";
|
|
59
|
+
botId: string;
|
|
60
|
+
}) | (BotRuntimeBindingBase & {
|
|
61
|
+
scope: "group-member";
|
|
62
|
+
botId: string;
|
|
63
|
+
}) | (BotRuntimeBindingBase & {
|
|
64
|
+
scope: "group-controller";
|
|
65
|
+
});
|
|
66
|
+
export {};
|
|
@@ -7254,12 +7254,12 @@ var init_adapter_catalog = __esm(() => {
|
|
|
7254
7254
|
codex: {
|
|
7255
7255
|
packageName: "@agentclientprotocol/codex-acp",
|
|
7256
7256
|
binName: "codex-acp",
|
|
7257
|
-
defaultVersion: "1.
|
|
7257
|
+
defaultVersion: "1.12.0"
|
|
7258
7258
|
},
|
|
7259
7259
|
claude: {
|
|
7260
7260
|
packageName: "@agentclientprotocol/claude-agent-acp",
|
|
7261
7261
|
binName: "claude-agent-acp",
|
|
7262
|
-
defaultVersion: "0.
|
|
7262
|
+
defaultVersion: "0.78.0"
|
|
7263
7263
|
}
|
|
7264
7264
|
};
|
|
7265
7265
|
EXACT_SEMVER = /^(0|[1-9]\d*)\.(0|[1-9]\d*)\.(0|[1-9]\d*)(?:-[0-9A-Za-z-]+(?:\.[0-9A-Za-z-]+)*)?(?:\+[0-9A-Za-z-]+(?:\.[0-9A-Za-z-]+)*)?$/;
|
|
@@ -14539,8 +14539,9 @@ class RuntimeEngine {
|
|
|
14539
14539
|
}
|
|
14540
14540
|
} else if (event.type === "status") {
|
|
14541
14541
|
if (event.tag === "plan") {
|
|
14542
|
-
|
|
14543
|
-
|
|
14542
|
+
const entries = toPromptPlanEntries(event.entries);
|
|
14543
|
+
if (entries)
|
|
14544
|
+
sink({ type: "prompt.plan", entries });
|
|
14544
14545
|
return;
|
|
14545
14546
|
}
|
|
14546
14547
|
if (typeof event.used === "number" && typeof event.size === "number") {
|
|
@@ -16255,6 +16256,31 @@ async function buildRuntimeAttachments(media) {
|
|
|
16255
16256
|
}
|
|
16256
16257
|
return attachments;
|
|
16257
16258
|
}
|
|
16259
|
+
var PROMPT_PLAN_STATUSES = new Set(["pending", "in_progress", "completed"]);
|
|
16260
|
+
var PROMPT_PLAN_PRIORITIES = new Set(["high", "medium", "low"]);
|
|
16261
|
+
function toPromptPlanEntries(value) {
|
|
16262
|
+
if (!Array.isArray(value))
|
|
16263
|
+
return;
|
|
16264
|
+
if (value.length === 0)
|
|
16265
|
+
return [];
|
|
16266
|
+
const entries = [];
|
|
16267
|
+
for (const item of value) {
|
|
16268
|
+
if (typeof item !== "object" || item === null)
|
|
16269
|
+
continue;
|
|
16270
|
+
const record = item;
|
|
16271
|
+
const content = typeof record.content === "string" ? record.content.trim() : "";
|
|
16272
|
+
const status = typeof record.status === "string" ? record.status.trim() : "";
|
|
16273
|
+
if (!content || !PROMPT_PLAN_STATUSES.has(status))
|
|
16274
|
+
continue;
|
|
16275
|
+
const priority = typeof record.priority === "string" ? record.priority.trim() : "";
|
|
16276
|
+
entries.push({
|
|
16277
|
+
content,
|
|
16278
|
+
status,
|
|
16279
|
+
...PROMPT_PLAN_PRIORITIES.has(priority) ? { priority } : {}
|
|
16280
|
+
});
|
|
16281
|
+
}
|
|
16282
|
+
return entries.length > 0 ? entries : undefined;
|
|
16283
|
+
}
|
|
16258
16284
|
function mapRuntimeToolEvent(event) {
|
|
16259
16285
|
const toolCallId = event.toolCallId || `tc-${Date.now()}-${Math.random().toString(36).slice(2, 6)}`;
|
|
16260
16286
|
const title = (event.title ?? "").trim();
|
|
@@ -5872,12 +5872,12 @@ var init_adapter_catalog = __esm(() => {
|
|
|
5872
5872
|
codex: {
|
|
5873
5873
|
packageName: "@agentclientprotocol/codex-acp",
|
|
5874
5874
|
binName: "codex-acp",
|
|
5875
|
-
defaultVersion: "1.
|
|
5875
|
+
defaultVersion: "1.12.0"
|
|
5876
5876
|
},
|
|
5877
5877
|
claude: {
|
|
5878
5878
|
packageName: "@agentclientprotocol/claude-agent-acp",
|
|
5879
5879
|
binName: "claude-agent-acp",
|
|
5880
|
-
defaultVersion: "0.
|
|
5880
|
+
defaultVersion: "0.78.0"
|
|
5881
5881
|
}
|
|
5882
5882
|
};
|
|
5883
5883
|
EXACT_SEMVER = /^(0|[1-9]\d*)\.(0|[1-9]\d*)\.(0|[1-9]\d*)(?:-[0-9A-Za-z-]+(?:\.[0-9A-Za-z-]+)*)?(?:\+[0-9A-Za-z-]+(?:\.[0-9A-Za-z-]+)*)?$/;
|
|
@@ -7157,6 +7157,7 @@ async function* mapEvents(events) {
|
|
|
7157
7157
|
};
|
|
7158
7158
|
}
|
|
7159
7159
|
} else if (event.type === "status") {
|
|
7160
|
+
const planEntries = normalizeAdapterPlanEntries(event.entries);
|
|
7160
7161
|
yield {
|
|
7161
7162
|
type: "status",
|
|
7162
7163
|
text: event.text,
|
|
@@ -7165,7 +7166,8 @@ async function* mapEvents(events) {
|
|
|
7165
7166
|
...event.size !== undefined ? { size: event.size } : {},
|
|
7166
7167
|
...event.cost ? { cost: event.cost } : {},
|
|
7167
7168
|
...event.breakdown ? { breakdown: event.breakdown } : {},
|
|
7168
|
-
...event.availableCommands ? { availableCommands: event.availableCommands } : {}
|
|
7169
|
+
...event.availableCommands ? { availableCommands: event.availableCommands } : {},
|
|
7170
|
+
...planEntries !== undefined ? { entries: planEntries } : {}
|
|
7169
7171
|
};
|
|
7170
7172
|
} else if (event.type === "tool_call") {
|
|
7171
7173
|
const isInitialToolEvent = typeof event.toolCallId === "string" ? !toolCalls.has(event.toolCallId) : event.tag !== "tool_call_update";
|
|
@@ -7188,6 +7190,31 @@ async function* mapEvents(events) {
|
|
|
7188
7190
|
}
|
|
7189
7191
|
}
|
|
7190
7192
|
}
|
|
7193
|
+
var ADAPTER_PLAN_STATUSES = new Set(["pending", "in_progress", "completed"]);
|
|
7194
|
+
var ADAPTER_PLAN_PRIORITIES = new Set(["high", "medium", "low"]);
|
|
7195
|
+
function normalizeAdapterPlanEntries(value) {
|
|
7196
|
+
if (!Array.isArray(value))
|
|
7197
|
+
return;
|
|
7198
|
+
if (value.length === 0)
|
|
7199
|
+
return [];
|
|
7200
|
+
const entries = [];
|
|
7201
|
+
for (const entry of value) {
|
|
7202
|
+
if (typeof entry !== "object" || entry === null)
|
|
7203
|
+
continue;
|
|
7204
|
+
const record = entry;
|
|
7205
|
+
const content = typeof record.content === "string" ? record.content.trim() : "";
|
|
7206
|
+
const status = typeof record.status === "string" ? record.status.trim() : "";
|
|
7207
|
+
if (!content || !ADAPTER_PLAN_STATUSES.has(status))
|
|
7208
|
+
continue;
|
|
7209
|
+
const priority = typeof record.priority === "string" ? record.priority.trim() : "";
|
|
7210
|
+
entries.push({
|
|
7211
|
+
content,
|
|
7212
|
+
status,
|
|
7213
|
+
...ADAPTER_PLAN_PRIORITIES.has(priority) ? { priority } : {}
|
|
7214
|
+
});
|
|
7215
|
+
}
|
|
7216
|
+
return entries.length > 0 ? entries : undefined;
|
|
7217
|
+
}
|
|
7191
7218
|
async function mapResult(result) {
|
|
7192
7219
|
const settled = await result;
|
|
7193
7220
|
if (settled.status === "failed") {
|
package/dist/cli.js
CHANGED
|
@@ -4355,12 +4355,12 @@ var init_adapter_catalog = __esm(() => {
|
|
|
4355
4355
|
codex: {
|
|
4356
4356
|
packageName: "@agentclientprotocol/codex-acp",
|
|
4357
4357
|
binName: "codex-acp",
|
|
4358
|
-
defaultVersion: "1.
|
|
4358
|
+
defaultVersion: "1.12.0"
|
|
4359
4359
|
},
|
|
4360
4360
|
claude: {
|
|
4361
4361
|
packageName: "@agentclientprotocol/claude-agent-acp",
|
|
4362
4362
|
binName: "claude-agent-acp",
|
|
4363
|
-
defaultVersion: "0.
|
|
4363
|
+
defaultVersion: "0.78.0"
|
|
4364
4364
|
}
|
|
4365
4365
|
};
|
|
4366
4366
|
EXACT_SEMVER = /^(0|[1-9]\d*)\.(0|[1-9]\d*)\.(0|[1-9]\d*)(?:-[0-9A-Za-z-]+(?:\.[0-9A-Za-z-]+)*)?(?:\+[0-9A-Za-z-]+(?:\.[0-9A-Za-z-]+)*)?$/;
|
|
@@ -30373,7 +30373,11 @@ function createEmptyState() {
|
|
|
30373
30373
|
chat_contexts: {},
|
|
30374
30374
|
native_session_lists: {},
|
|
30375
30375
|
orchestration: createEmptyOrchestrationState(),
|
|
30376
|
-
scheduled_tasks: {}
|
|
30376
|
+
scheduled_tasks: {},
|
|
30377
|
+
bots: {},
|
|
30378
|
+
conversations: {},
|
|
30379
|
+
conversation_topics: {},
|
|
30380
|
+
bot_runtime_bindings: {}
|
|
30377
30381
|
};
|
|
30378
30382
|
}
|
|
30379
30383
|
var init_types4 = () => {};
|
|
@@ -30730,7 +30734,17 @@ function isSessionRecord(value) {
|
|
|
30730
30734
|
if (!isRecord4(value)) {
|
|
30731
30735
|
return false;
|
|
30732
30736
|
}
|
|
30733
|
-
return isString(value.alias) && isString(value.agent) && isString(value.workspace) && isString(value.transport_session) && (value.logical_session_id === undefined || isLogicalSessionId(value.logical_session_id)) && isSessionSource(value.source) && isOptionalString(value.agent_session_id) && isOptionalString(value.agent_session_title) && isOptionalString(value.agent_session_updated_at) && isOptionalString(value.attached_at) && isOptionalString(value.transport_agent_command) && isOptionalString(value.transport_acpx_agent) && (value.transport_agent_argv === undefined || isStringArray(value.transport_agent_argv)) && (value.transport_engine === undefined || value.transport_engine === "cli" || value.transport_engine === "runtime") && isOptionalString(value.mode_id) && isOptionalString(value.effort) && (value.reply_mode === undefined || isReplyMode2(value.reply_mode)) && isString(value.created_at) && isString(value.last_used_at);
|
|
30737
|
+
return isString(value.alias) && isString(value.agent) && isString(value.workspace) && isString(value.transport_session) && (value.logical_session_id === undefined || isLogicalSessionId(value.logical_session_id)) && isSessionSource(value.source) && isOptionalString(value.agent_session_id) && isOptionalString(value.agent_session_title) && isOptionalString(value.agent_session_updated_at) && isOptionalString(value.attached_at) && isOptionalString(value.transport_agent_command) && isOptionalString(value.transport_acpx_agent) && (value.transport_agent_argv === undefined || isStringArray(value.transport_agent_argv)) && (value.transport_engine === undefined || value.transport_engine === "cli" || value.transport_engine === "runtime") && isOptionalString(value.mode_id) && isOptionalString(value.effort) && (value.reply_mode === undefined || isReplyMode2(value.reply_mode)) && isString(value.created_at) && isString(value.last_used_at) && (value.owner === undefined || isLogicalSessionOwner(value.owner));
|
|
30738
|
+
}
|
|
30739
|
+
function isLogicalSessionOwner(value) {
|
|
30740
|
+
if (!isRecord4(value)) {
|
|
30741
|
+
return false;
|
|
30742
|
+
}
|
|
30743
|
+
if (value.kind !== "bot-direct" && value.kind !== "group-member" && value.kind !== "group-controller" || !isString(value.bindingId) || value.bindingId.length === 0) {
|
|
30744
|
+
return false;
|
|
30745
|
+
}
|
|
30746
|
+
const optional3 = (field) => value[field] === undefined || isString(value[field]) && value[field].length > 0;
|
|
30747
|
+
return optional3("botId") && optional3("conversationId") && optional3("topicId");
|
|
30734
30748
|
}
|
|
30735
30749
|
function parseSessions(raw, dropped, migrated) {
|
|
30736
30750
|
const sessions = {};
|
|
@@ -30822,6 +30836,108 @@ function parseScheduledTasks(raw, dropped) {
|
|
|
30822
30836
|
}
|
|
30823
30837
|
return tasks;
|
|
30824
30838
|
}
|
|
30839
|
+
function isBotProfile(value) {
|
|
30840
|
+
if (!isRecord4(value)) {
|
|
30841
|
+
return false;
|
|
30842
|
+
}
|
|
30843
|
+
return isString(value.id) && isString(value.name) && isOptionalString(value.avatar) && isOptionalString(value.role) && isOptionalString(value.instructions) && isString(value.agent) && isString(value.workspace) && isOptionalString(value.cwd) && isOptionalString(value.model) && isOptionalString(value.effort) && typeof value.enabled === "boolean" && (value.profileRevision === undefined || typeof value.profileRevision === "number" && Number.isInteger(value.profileRevision) && value.profileRevision >= 1) && isString(value.createdAt) && isString(value.updatedAt);
|
|
30844
|
+
}
|
|
30845
|
+
function parseBotProfiles(raw, dropped) {
|
|
30846
|
+
const source = sectionRecord(raw, "bots", dropped);
|
|
30847
|
+
const bots = {};
|
|
30848
|
+
for (const [id, value] of Object.entries(source)) {
|
|
30849
|
+
if (!isBotProfile(value) || value.id !== id) {
|
|
30850
|
+
dropped.push({ section: "bots", key: id, reason: "malformed bot profile" });
|
|
30851
|
+
continue;
|
|
30852
|
+
}
|
|
30853
|
+
bots[id] = {
|
|
30854
|
+
...value,
|
|
30855
|
+
profileRevision: value.profileRevision ?? 1
|
|
30856
|
+
};
|
|
30857
|
+
}
|
|
30858
|
+
return bots;
|
|
30859
|
+
}
|
|
30860
|
+
function isUniqueStringArray(value) {
|
|
30861
|
+
return isStringArray(value) && new Set(value).size === value.length;
|
|
30862
|
+
}
|
|
30863
|
+
function isConversationRecord(value) {
|
|
30864
|
+
if (!isRecord4(value)) {
|
|
30865
|
+
return false;
|
|
30866
|
+
}
|
|
30867
|
+
if (!isString(value.id) || !isString(value.title) || !isOptionalString(value.description) || !isUniqueStringArray(value.botIds) || !isOptionalString(value.leadBotId) || !isString(value.createdAt) || !isString(value.updatedAt)) {
|
|
30868
|
+
return false;
|
|
30869
|
+
}
|
|
30870
|
+
if (value.lifecycle !== undefined && value.lifecycle !== "active" && value.lifecycle !== "deleting") {
|
|
30871
|
+
return false;
|
|
30872
|
+
}
|
|
30873
|
+
if (value.leadBotId !== undefined && !value.botIds.includes(value.leadBotId)) {
|
|
30874
|
+
return false;
|
|
30875
|
+
}
|
|
30876
|
+
if (value.kind === "bot") {
|
|
30877
|
+
return value.botIds.length === 1;
|
|
30878
|
+
}
|
|
30879
|
+
if (value.kind === "group") {
|
|
30880
|
+
return value.botIds.length >= 2;
|
|
30881
|
+
}
|
|
30882
|
+
return false;
|
|
30883
|
+
}
|
|
30884
|
+
function parseConversations(raw, dropped) {
|
|
30885
|
+
const source = sectionRecord(raw, "conversations", dropped);
|
|
30886
|
+
const conversations = {};
|
|
30887
|
+
for (const [id, value] of Object.entries(source)) {
|
|
30888
|
+
if (!isConversationRecord(value) || value.id !== id) {
|
|
30889
|
+
dropped.push({ section: "conversations", key: id, reason: "malformed conversation record" });
|
|
30890
|
+
continue;
|
|
30891
|
+
}
|
|
30892
|
+
conversations[id] = value;
|
|
30893
|
+
}
|
|
30894
|
+
return conversations;
|
|
30895
|
+
}
|
|
30896
|
+
function isConversationTopic(value) {
|
|
30897
|
+
if (!isRecord4(value)) {
|
|
30898
|
+
return false;
|
|
30899
|
+
}
|
|
30900
|
+
return isString(value.id) && isString(value.conversationId) && isString(value.title) && (value.status === "active" || value.status === "archived" || value.status === "deleting") && isString(value.createdAt) && isString(value.updatedAt);
|
|
30901
|
+
}
|
|
30902
|
+
function parseConversationTopics(raw, dropped) {
|
|
30903
|
+
const source = sectionRecord(raw, "conversation_topics", dropped);
|
|
30904
|
+
const topics = {};
|
|
30905
|
+
for (const [id, value] of Object.entries(source)) {
|
|
30906
|
+
if (!isConversationTopic(value) || value.id !== id) {
|
|
30907
|
+
dropped.push({ section: "conversation_topics", key: id, reason: "malformed conversation topic" });
|
|
30908
|
+
continue;
|
|
30909
|
+
}
|
|
30910
|
+
topics[id] = value;
|
|
30911
|
+
}
|
|
30912
|
+
return topics;
|
|
30913
|
+
}
|
|
30914
|
+
function isBotRuntimeBinding(value) {
|
|
30915
|
+
if (!isRecord4(value)) {
|
|
30916
|
+
return false;
|
|
30917
|
+
}
|
|
30918
|
+
if (!isString(value.id) || !isString(value.conversationId) || !isString(value.topicId) || !isString(value.logicalSessionId) || !isString(value.sessionAlias) || !isString(value.createdAt) || !isString(value.updatedAt)) {
|
|
30919
|
+
return false;
|
|
30920
|
+
}
|
|
30921
|
+
if (value.scope === "bot-direct" || value.scope === "group-member") {
|
|
30922
|
+
return isString(value.botId) && value.botId.length > 0;
|
|
30923
|
+
}
|
|
30924
|
+
if (value.scope === "group-controller") {
|
|
30925
|
+
return value.botId === undefined;
|
|
30926
|
+
}
|
|
30927
|
+
return false;
|
|
30928
|
+
}
|
|
30929
|
+
function parseBotRuntimeBindings(raw, dropped) {
|
|
30930
|
+
const source = sectionRecord(raw, "bot_runtime_bindings", dropped);
|
|
30931
|
+
const bindings = {};
|
|
30932
|
+
for (const [id, value] of Object.entries(source)) {
|
|
30933
|
+
if (!isBotRuntimeBinding(value) || value.id !== id) {
|
|
30934
|
+
dropped.push({ section: "bot_runtime_bindings", key: id, reason: "malformed bot runtime binding" });
|
|
30935
|
+
continue;
|
|
30936
|
+
}
|
|
30937
|
+
bindings[id] = value;
|
|
30938
|
+
}
|
|
30939
|
+
return bindings;
|
|
30940
|
+
}
|
|
30825
30941
|
function parseState(raw, path3, dropped = [], migrated = []) {
|
|
30826
30942
|
if (!isRecord4(raw)) {
|
|
30827
30943
|
throw new Error(`state file "${path3}" must contain a JSON object`);
|
|
@@ -30834,7 +30950,11 @@ function parseState(raw, path3, dropped = [], migrated = []) {
|
|
|
30834
30950
|
chat_contexts: parseChatContexts(sectionRecord(raw.chat_contexts, "chat_contexts", dropped), dropped),
|
|
30835
30951
|
native_session_lists: parseNativeSessionLists(raw.native_session_lists),
|
|
30836
30952
|
orchestration: orchestration3,
|
|
30837
|
-
scheduled_tasks: parseScheduledTasks(raw.scheduled_tasks, dropped)
|
|
30953
|
+
scheduled_tasks: parseScheduledTasks(raw.scheduled_tasks, dropped),
|
|
30954
|
+
bots: parseBotProfiles(raw.bots, dropped),
|
|
30955
|
+
conversations: parseConversations(raw.conversations, dropped),
|
|
30956
|
+
conversation_topics: parseConversationTopics(raw.conversation_topics, dropped),
|
|
30957
|
+
bot_runtime_bindings: parseBotRuntimeBindings(raw.bot_runtime_bindings, dropped)
|
|
30838
30958
|
};
|
|
30839
30959
|
}
|
|
30840
30960
|
function repairExternalCoordinatorIdentityCollisions(sessions, orchestration3, dropped) {
|
|
@@ -42471,6 +42591,7 @@ function lockForPhysicalKey(physicalKey) {
|
|
|
42471
42591
|
}
|
|
42472
42592
|
async function removeAliasWithPhysicalLifecycle(options) {
|
|
42473
42593
|
const { sessions, transport, session: session3, internalAlias } = options;
|
|
42594
|
+
const policy = options.physicalFailurePolicy ?? "legacy-cli-best-effort";
|
|
42474
42595
|
const groupKey = physicalLifecycleKeyForResolvedSession(session3);
|
|
42475
42596
|
const isRuntime = session3.transportEngine === "runtime";
|
|
42476
42597
|
return lockForPhysicalKey(groupKey).run(async () => {
|
|
@@ -42500,9 +42621,14 @@ async function removeAliasWithPhysicalLifecycle(options) {
|
|
|
42500
42621
|
await transport.deleteSession(session3);
|
|
42501
42622
|
action = "deleted";
|
|
42502
42623
|
} catch (error2) {
|
|
42624
|
+
if (policy === "strict") {
|
|
42625
|
+
throw error2;
|
|
42626
|
+
}
|
|
42503
42627
|
transportTeardownWarning = error2 instanceof Error ? error2.message : String(error2);
|
|
42504
42628
|
action = "logical-only";
|
|
42505
42629
|
}
|
|
42630
|
+
} else if (remaining === 0 && policy === "strict") {
|
|
42631
|
+
throw new Error(`cannot hard-delete last CLI alias "${internalAlias}": transport has no deleteSession operation`);
|
|
42506
42632
|
} else {
|
|
42507
42633
|
action = "logical-only";
|
|
42508
42634
|
}
|
|
@@ -54938,6 +55064,10 @@ function replaceRuntimeState(target, source) {
|
|
|
54938
55064
|
target.chat_contexts = source.chat_contexts;
|
|
54939
55065
|
target.orchestration = source.orchestration;
|
|
54940
55066
|
target.scheduled_tasks = source.scheduled_tasks;
|
|
55067
|
+
target.bots = source.bots;
|
|
55068
|
+
target.conversations = source.conversations;
|
|
55069
|
+
target.conversation_topics = source.conversation_topics;
|
|
55070
|
+
target.bot_runtime_bindings = source.bot_runtime_bindings;
|
|
54941
55071
|
}
|
|
54942
55072
|
|
|
54943
55073
|
// src/sessions/transport-engine.ts
|
|
@@ -55139,8 +55269,8 @@ class SessionService {
|
|
|
55139
55269
|
...this.permissionInteractionCapable !== undefined ? { permissionInteractionCapable: this.permissionInteractionCapable } : {}
|
|
55140
55270
|
}).engine;
|
|
55141
55271
|
}
|
|
55142
|
-
async createSession(alias, agent3, workspace3) {
|
|
55143
|
-
return await this.createLogicalSession(alias, agent3, workspace3, `${workspace3}:${alias}
|
|
55272
|
+
async createSession(alias, agent3, workspace3, options) {
|
|
55273
|
+
return await this.createLogicalSession(alias, agent3, workspace3, `${workspace3}:${alias}`, undefined, undefined, undefined, undefined, options);
|
|
55144
55274
|
}
|
|
55145
55275
|
listAllResolvedSessions() {
|
|
55146
55276
|
const seen = new Set;
|
|
@@ -55547,6 +55677,9 @@ class SessionService {
|
|
|
55547
55677
|
getLogicalSessionRecord(alias) {
|
|
55548
55678
|
return this.state.sessions[alias] ?? null;
|
|
55549
55679
|
}
|
|
55680
|
+
getLogicalSessionById(logicalSessionId) {
|
|
55681
|
+
return Object.values(this.state.sessions).find((session3) => session3.logical_session_id === logicalSessionId) ?? null;
|
|
55682
|
+
}
|
|
55550
55683
|
listLogicalSessionRecords() {
|
|
55551
55684
|
return Object.values(this.state.sessions);
|
|
55552
55685
|
}
|
|
@@ -56166,7 +56299,7 @@ class SessionService {
|
|
|
56166
56299
|
}
|
|
56167
56300
|
return input.sameAgentExistingEngine ?? siblingEngine ?? input.fallback();
|
|
56168
56301
|
}
|
|
56169
|
-
async createLogicalSession(alias, agent3, workspace3, transportSession, transportAgentCommand, native, transportAcpxAgent, transportAgentArgv) {
|
|
56302
|
+
async createLogicalSession(alias, agent3, workspace3, transportSession, transportAgentCommand, native, transportAcpxAgent, transportAgentArgv, extras) {
|
|
56170
56303
|
return await this.mutate(async () => {
|
|
56171
56304
|
this.validateSession(alias, agent3, workspace3);
|
|
56172
56305
|
if (Object.keys(this.state.orchestration.externalCoordinators).some((coordinatorSession) => sameCoordinatorSession(coordinatorSession, transportSession))) {
|
|
@@ -56191,8 +56324,8 @@ class SessionService {
|
|
|
56191
56324
|
...transportAcpxAgent ? { transport_acpx_agent: transportAcpxAgent } : sameAgentExisting?.transport_acpx_agent ? { transport_acpx_agent: sameAgentExisting.transport_acpx_agent } : {},
|
|
56192
56325
|
...transportAgentArgv && transportAgentArgv.length > 0 ? { transport_agent_argv: [...transportAgentArgv] } : sameAgentExisting?.transport_agent_argv ? { transport_agent_argv: [...sameAgentExisting.transport_agent_argv] } : {},
|
|
56193
56326
|
mode_id: sameAgentExisting?.mode_id,
|
|
56194
|
-
model: sameAgentExisting?.model,
|
|
56195
|
-
effort: sameAgentExisting?.effort,
|
|
56327
|
+
model: extras?.model ?? sameAgentExisting?.model,
|
|
56328
|
+
effort: extras?.effort ?? sameAgentExisting?.effort,
|
|
56196
56329
|
reply_mode: sameAgentExisting?.reply_mode,
|
|
56197
56330
|
display_name: sameAgentExisting?.display_name,
|
|
56198
56331
|
transport_engine: this.resolveEngineWithPhysicalInheritance({
|
|
@@ -56206,7 +56339,8 @@ class SessionService {
|
|
|
56206
56339
|
...sameAgentExisting ? { sameAgentExisting } : {}
|
|
56207
56340
|
}),
|
|
56208
56341
|
created_at: existingSession?.created_at ?? now,
|
|
56209
|
-
last_used_at: now
|
|
56342
|
+
last_used_at: now,
|
|
56343
|
+
...extras?.owner ? { owner: extras.owner } : {}
|
|
56210
56344
|
};
|
|
56211
56345
|
const nextState = structuredClone(this.state);
|
|
56212
56346
|
nextState.sessions[alias] = session3;
|
|
@@ -63016,6 +63150,7 @@ ${envelope}` : envelope;
|
|
|
63016
63150
|
return {
|
|
63017
63151
|
ok: false,
|
|
63018
63152
|
errorMessage,
|
|
63153
|
+
...!timedOut && signal.aborted ? { cancelled: true } : {},
|
|
63019
63154
|
...internalAlias && priorTransportSession ? { postTurnDetection: { internalAlias, priorTransportSession } } : {}
|
|
63020
63155
|
};
|
|
63021
63156
|
}
|
|
@@ -63440,10 +63575,13 @@ class TurnQueue {
|
|
|
63440
63575
|
return {
|
|
63441
63576
|
ok: result.ok,
|
|
63442
63577
|
...result.text !== undefined ? { text: result.text } : {},
|
|
63443
|
-
...result.errorMessage !== undefined ? { errorMessage: result.errorMessage } : {}
|
|
63578
|
+
...result.errorMessage !== undefined ? { errorMessage: result.errorMessage } : {},
|
|
63579
|
+
...result.cancelled ? { cancelled: true } : {}
|
|
63444
63580
|
};
|
|
63445
63581
|
}
|
|
63446
63582
|
advanceQueue(key) {
|
|
63583
|
+
const finished = this.inFlight.get(key);
|
|
63584
|
+
this.recordSettledRequestId(finished?.promptRequestId);
|
|
63447
63585
|
const interrupt = this.pendingInterrupts.get(key);
|
|
63448
63586
|
if (interrupt) {
|
|
63449
63587
|
this.pendingInterrupts.delete(key);
|
|
@@ -63498,6 +63636,26 @@ class TurnQueue {
|
|
|
63498
63636
|
entry.controller.abort();
|
|
63499
63637
|
return true;
|
|
63500
63638
|
}
|
|
63639
|
+
cancelTurnForPromptRequest(chatKey, sessionAlias, promptRequestId, concurrencyKey) {
|
|
63640
|
+
const key = this.resolveKey(chatKey, sessionAlias, concurrencyKey);
|
|
63641
|
+
const entry = this.inFlight.get(key);
|
|
63642
|
+
if (!entry || entry.promptRequestId !== promptRequestId) {
|
|
63643
|
+
return false;
|
|
63644
|
+
}
|
|
63645
|
+
entry.controller.abort();
|
|
63646
|
+
return true;
|
|
63647
|
+
}
|
|
63648
|
+
inspectPromptRequest(chatKey, sessionAlias, promptRequestId, concurrencyKey) {
|
|
63649
|
+
const key = this.resolveKey(chatKey, sessionAlias, concurrencyKey);
|
|
63650
|
+
const entry = this.inFlight.get(key);
|
|
63651
|
+
if (entry?.promptRequestId === promptRequestId) {
|
|
63652
|
+
return "in-flight";
|
|
63653
|
+
}
|
|
63654
|
+
if (this.hasSettledRequestId(promptRequestId)) {
|
|
63655
|
+
return "settled";
|
|
63656
|
+
}
|
|
63657
|
+
return "absent";
|
|
63658
|
+
}
|
|
63501
63659
|
async clearSession(chatKey, sessionAlias, concurrencyKey) {
|
|
63502
63660
|
const key = this.resolveKey(chatKey, sessionAlias, concurrencyKey);
|
|
63503
63661
|
const guardPreexisting = this.removing.has(key);
|
|
@@ -64084,26 +64242,40 @@ class ControlService {
|
|
|
64084
64242
|
return task;
|
|
64085
64243
|
}
|
|
64086
64244
|
async prompt(input) {
|
|
64245
|
+
return this.submitHumanPrompt(input, true);
|
|
64246
|
+
}
|
|
64247
|
+
async promptImmediate(input) {
|
|
64248
|
+
return this.submitHumanPrompt(input, false);
|
|
64249
|
+
}
|
|
64250
|
+
submitHumanPrompt(input, queueable) {
|
|
64087
64251
|
const channelId = getChannelIdFromChatKey(input.chatKey);
|
|
64088
64252
|
const internalAlias = this.deps.sessions.getResolvedSessionByInternalAlias?.(input.sessionAlias)?.alias ?? this.deps.sessions.getResolvedSessionByInternalAlias?.(toInternalSessionAlias(channelId, input.sessionAlias))?.alias ?? scopeDisplayAliasToInternal(channelId, input.sessionAlias);
|
|
64089
64253
|
const configTail = this.sessionConfigSetTails.get(internalAlias) ?? this.sessionConfigSetTails.get(input.sessionAlias);
|
|
64254
|
+
const turnOrigin = queueable ? "human" : input.executionOrigin === "human" ? "human" : "orchestration";
|
|
64255
|
+
const submit = () => {
|
|
64256
|
+
if (input.abortSignal?.aborted) {
|
|
64257
|
+
return Promise.resolve({ ok: false, cancelled: true, errorMessage: "cancelled" });
|
|
64258
|
+
}
|
|
64259
|
+
return this.turnQueue.submit({
|
|
64260
|
+
chatKey: input.chatKey,
|
|
64261
|
+
sessionAlias: input.sessionAlias,
|
|
64262
|
+
concurrencyKey: internalAlias,
|
|
64263
|
+
text: input.text,
|
|
64264
|
+
senderId: input.senderId,
|
|
64265
|
+
turnOrigin,
|
|
64266
|
+
queueable,
|
|
64267
|
+
...input.isOwner !== undefined ? { isOwner: input.isOwner } : {},
|
|
64268
|
+
...input.accountId !== undefined ? { accountId: input.accountId } : {},
|
|
64269
|
+
...input.media !== undefined ? { media: input.media } : {},
|
|
64270
|
+
...input.agentMentions !== undefined ? { agentMentions: input.agentMentions } : {},
|
|
64271
|
+
...input.promptRequestId !== undefined ? { promptRequestId: input.promptRequestId } : {},
|
|
64272
|
+
...input.abortSignal !== undefined ? { abortSignal: input.abortSignal } : {}
|
|
64273
|
+
});
|
|
64274
|
+
};
|
|
64090
64275
|
if (configTail) {
|
|
64091
|
-
|
|
64276
|
+
return configTail.catch(() => {}).then(submit);
|
|
64092
64277
|
}
|
|
64093
|
-
return
|
|
64094
|
-
chatKey: input.chatKey,
|
|
64095
|
-
sessionAlias: input.sessionAlias,
|
|
64096
|
-
concurrencyKey: internalAlias,
|
|
64097
|
-
text: input.text,
|
|
64098
|
-
senderId: input.senderId,
|
|
64099
|
-
turnOrigin: "human",
|
|
64100
|
-
queueable: true,
|
|
64101
|
-
...input.isOwner !== undefined ? { isOwner: input.isOwner } : {},
|
|
64102
|
-
...input.accountId !== undefined ? { accountId: input.accountId } : {},
|
|
64103
|
-
...input.media !== undefined ? { media: input.media } : {},
|
|
64104
|
-
...input.agentMentions !== undefined ? { agentMentions: input.agentMentions } : {},
|
|
64105
|
-
...input.promptRequestId !== undefined ? { promptRequestId: input.promptRequestId } : {}
|
|
64106
|
-
});
|
|
64278
|
+
return submit();
|
|
64107
64279
|
}
|
|
64108
64280
|
async runScheduledTurn(input) {
|
|
64109
64281
|
const channelId = getChannelIdFromChatKey(input.chatKey);
|
|
@@ -64142,6 +64314,16 @@ class ControlService {
|
|
|
64142
64314
|
const internalAlias = this.deps.sessions.getResolvedSessionByInternalAlias?.(sessionAlias)?.alias ?? this.deps.sessions.getResolvedSessionByInternalAlias?.(toInternalSessionAlias(channelId, sessionAlias))?.alias ?? scopeDisplayAliasToInternal(channelId, sessionAlias);
|
|
64143
64315
|
return this.turnQueue.cancelTurn(chatKey, sessionAlias, internalAlias);
|
|
64144
64316
|
}
|
|
64317
|
+
cancelTurnForPromptRequest(chatKey, sessionAlias, promptRequestId) {
|
|
64318
|
+
const channelId = getChannelIdFromChatKey(chatKey);
|
|
64319
|
+
const internalAlias = this.deps.sessions.getResolvedSessionByInternalAlias?.(sessionAlias)?.alias ?? this.deps.sessions.getResolvedSessionByInternalAlias?.(toInternalSessionAlias(channelId, sessionAlias))?.alias ?? scopeDisplayAliasToInternal(channelId, sessionAlias);
|
|
64320
|
+
return this.turnQueue.cancelTurnForPromptRequest(chatKey, sessionAlias, promptRequestId, internalAlias);
|
|
64321
|
+
}
|
|
64322
|
+
inspectPromptRequest(chatKey, sessionAlias, promptRequestId) {
|
|
64323
|
+
const channelId = getChannelIdFromChatKey(chatKey);
|
|
64324
|
+
const internalAlias = this.deps.sessions.getResolvedSessionByInternalAlias?.(sessionAlias)?.alias ?? this.deps.sessions.getResolvedSessionByInternalAlias?.(toInternalSessionAlias(channelId, sessionAlias))?.alias ?? scopeDisplayAliasToInternal(channelId, sessionAlias);
|
|
64325
|
+
return this.turnQueue.inspectPromptRequest(chatKey, sessionAlias, promptRequestId, internalAlias);
|
|
64326
|
+
}
|
|
64145
64327
|
async submitPeerTurn(input) {
|
|
64146
64328
|
const channelId = getChannelIdFromChatKey(input.chatKey);
|
|
64147
64329
|
const internalAlias = input.boundSessionAlias ?? this.deps.sessions.getResolvedSessionByInternalAlias?.(input.sessionAlias)?.alias ?? this.deps.sessions.getResolvedSessionByInternalAlias?.(toInternalSessionAlias(channelId, input.sessionAlias))?.alias ?? scopeDisplayAliasToInternal(channelId, input.sessionAlias);
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import type { SessionService } from "../sessions/session-service";
|
|
2
2
|
import type { ResolvedSession, SessionTransport } from "../transport/types";
|
|
3
|
+
export type PhysicalFailurePolicy = "legacy-cli-best-effort" | "strict";
|
|
3
4
|
export interface PhysicalRemoveOutcome {
|
|
4
5
|
wasActive: boolean;
|
|
5
6
|
/**
|
|
@@ -26,6 +27,14 @@ export declare function removeAliasWithPhysicalLifecycle(options: {
|
|
|
26
27
|
transport: Pick<SessionTransport, "releaseLogicalSession" | "deleteSession">;
|
|
27
28
|
session: ResolvedSession;
|
|
28
29
|
internalAlias: string;
|
|
30
|
+
/**
|
|
31
|
+
* Default `legacy-cli-best-effort` keeps `/session rm` semantics: a CLI
|
|
32
|
+
* last-owner `deleteSession` failure records a warning and still removes
|
|
33
|
+
* the LogicalSession. `strict` is the Bot/Conversation owned-session
|
|
34
|
+
* path: any Runtime or CLI physical failure throws BEFORE the logical row
|
|
35
|
+
* disappears so callers keep the retry handle.
|
|
36
|
+
*/
|
|
37
|
+
physicalFailurePolicy?: PhysicalFailurePolicy;
|
|
29
38
|
}): Promise<PhysicalRemoveOutcome>;
|
|
30
39
|
export interface ProvisionalSessionCleanup {
|
|
31
40
|
sessions: SessionService;
|
package/dist/config/types.d.ts
CHANGED
|
@@ -71,7 +71,7 @@ export interface TransportConfig {
|
|
|
71
71
|
*/
|
|
72
72
|
turnIdleTimeoutSeconds?: number;
|
|
73
73
|
/**
|
|
74
|
-
* Advanced acpx embedding-host ceilings (acpx 0.15.1
|
|
74
|
+
* Advanced acpx embedding-host ceilings (acpx 0.15.1+, plan B5).
|
|
75
75
|
* `acpxMaxIncomingMessageBytes` overrides the 64 MiB default ceiling on
|
|
76
76
|
* agent → acpx inbound ACP messages (`0` = unlimited — avoid unless a real
|
|
77
77
|
* workload needs it); `acpxTerminalMaxOutputBytes` caps retained
|
|
@@ -7,6 +7,7 @@ import type { ScheduledTaskRecord } from "../scheduled/scheduled-types";
|
|
|
7
7
|
import type { CancelTaskInput, OrchestrationService, OrchestrationTaskFilter } from "../orchestration/orchestration-service";
|
|
8
8
|
import type { OrchestrationTaskRecord } from "../orchestration/orchestration-types";
|
|
9
9
|
import type { AgentMessageCompletion, AgentMessageMode } from "../orchestration/agent-messaging-types";
|
|
10
|
+
import type { PermissionInteractionOrigin } from "../permissions/permission-types.js";
|
|
10
11
|
import type { ControlEventBus } from "./control-event-bus";
|
|
11
12
|
import type { AgentCatalogEntry } from "../config/agent-catalog";
|
|
12
13
|
import { type BrowseDirsResult, type DirListing, type FileContent, type SearchOptions, type SearchResult, type WorkspaceDiff } from "./workspace-fs";
|
|
@@ -221,11 +222,23 @@ export interface ControlPromptInput {
|
|
|
221
222
|
* turn-started so the hub can tie a queued prompt back to its pre-written inbound
|
|
222
223
|
* row (see PromptPayload.promptRequestId). */
|
|
223
224
|
promptRequestId?: string;
|
|
225
|
+
/** Conversation pre-admission cancel. Checked after any config-tail wait and
|
|
226
|
+
* immediately before TurnQueue.submit so a cancelled Run never starts. */
|
|
227
|
+
abortSignal?: AbortSignal;
|
|
228
|
+
/**
|
|
229
|
+
* Conversation execution provenance, derived by ConversationStore at claim
|
|
230
|
+
* from the live authority epoch. `promptImmediate` fail-closes to
|
|
231
|
+
* orchestration unless this is exactly `"human"`. Interactive `prompt()`
|
|
232
|
+
* ignores it and is always human. Omitting it cannot mint human authority.
|
|
233
|
+
*/
|
|
234
|
+
executionOrigin?: PermissionInteractionOrigin;
|
|
224
235
|
}
|
|
225
236
|
export interface ControlPromptResult {
|
|
226
237
|
ok: boolean;
|
|
227
238
|
text?: string;
|
|
228
239
|
errorMessage?: string;
|
|
240
|
+
/** Proven cancellation (AbortSignal / user Stop), not an error string match. */
|
|
241
|
+
cancelled?: boolean;
|
|
229
242
|
/** True when this prompt did not run immediately and was instead appended to the
|
|
230
243
|
* per-session server-side queue (a turn was already in flight). */
|
|
231
244
|
queued?: boolean;
|
|
@@ -386,6 +399,14 @@ export declare class ControlService {
|
|
|
386
399
|
getOrchestrationTask(taskId: string): Promise<OrchestrationTaskRecord | null>;
|
|
387
400
|
cancelOrchestrationTask(input: CancelTaskInput): Promise<OrchestrationTaskRecord>;
|
|
388
401
|
prompt(input: ControlPromptInput): Promise<ControlPromptResult>;
|
|
402
|
+
/**
|
|
403
|
+
* Conversation execution seam: same TurnQueue / SessionTurnRunner path as
|
|
404
|
+
* `prompt()`, but never FIFO-enqueues when the session lane is busy.
|
|
405
|
+
* Turn origin is the store-derived `executionOrigin` (fail-closed to
|
|
406
|
+
* orchestration). ConversationStore already owns durable queuing.
|
|
407
|
+
*/
|
|
408
|
+
promptImmediate(input: ControlPromptInput): Promise<ControlPromptResult>;
|
|
409
|
+
private submitHumanPrompt;
|
|
389
410
|
/** Run a fired scheduled task as a real turn through the same machinery as a manual
|
|
390
411
|
* prompt — so it streams live and persists to history — while tagging turn-started
|
|
391
412
|
* with the prompt text + schedule origin so the hub records the inbound message and
|
|
@@ -395,6 +416,8 @@ export declare class ControlService {
|
|
|
395
416
|
isBusy(chatKey: string, sessionAlias: string): boolean;
|
|
396
417
|
isSessionBusy(internalAlias: string): boolean;
|
|
397
418
|
cancelTurn(chatKey: string, sessionAlias: string): boolean;
|
|
419
|
+
cancelTurnForPromptRequest(chatKey: string, sessionAlias: string, promptRequestId: string): boolean;
|
|
420
|
+
inspectPromptRequest(chatKey: string, sessionAlias: string, promptRequestId: string): "in-flight" | "settled" | "absent";
|
|
398
421
|
submitPeerTurn(input: {
|
|
399
422
|
chatKey: string;
|
|
400
423
|
sessionAlias: string;
|
|
@@ -36,6 +36,8 @@ export interface TurnResult {
|
|
|
36
36
|
ok: boolean;
|
|
37
37
|
text?: string;
|
|
38
38
|
errorMessage?: string;
|
|
39
|
+
/** Proven user-Stop / abort cancellation. Idle-timeout aborts omit this. */
|
|
40
|
+
cancelled?: boolean;
|
|
39
41
|
postTurnDetection?: {
|
|
40
42
|
internalAlias: string;
|
|
41
43
|
priorTransportSession: string;
|
|
@@ -150,6 +150,14 @@ export declare class TurnQueue {
|
|
|
150
150
|
private advanceQueue;
|
|
151
151
|
private drainQueuedPrompt;
|
|
152
152
|
cancelTurn(chatKey: string, sessionAlias: string, concurrencyKey?: string): boolean;
|
|
153
|
+
/**
|
|
154
|
+
* Abort the in-flight turn only when it is the given promptRequestId.
|
|
155
|
+
* A minted Conversation correlation id is not a lane-wide cancel: a later
|
|
156
|
+
* prompt on the same session must not be aborted, and a settled request
|
|
157
|
+
* must not be treated as cancelled just because Stop was pressed late.
|
|
158
|
+
*/
|
|
159
|
+
cancelTurnForPromptRequest(chatKey: string, sessionAlias: string, promptRequestId: string, concurrencyKey?: string): boolean;
|
|
160
|
+
inspectPromptRequest(chatKey: string, sessionAlias: string, promptRequestId: string, concurrencyKey?: string): "in-flight" | "settled" | "absent";
|
|
153
161
|
/** Tear down all turn state for a session that is being removed or archived: drop every
|
|
154
162
|
* queued prompt, abort a running turn, and wait (bounded) for it to unwind. The queue is
|
|
155
163
|
* cleared BEFORE the abort so the aborting turn's finally sees it empty and releases the
|
|
@@ -0,0 +1,117 @@
|
|
|
1
|
+
import type { BotProfileSnapshot } from "../bots/bot-types";
|
|
2
|
+
export type ConversationKind = "bot" | "group";
|
|
3
|
+
export type ConversationLifecycle = "active" | "deleting";
|
|
4
|
+
export type ConversationTopicStatus = "active" | "archived" | "deleting";
|
|
5
|
+
export type ConversationMessageRole = "human" | "bot" | "system";
|
|
6
|
+
export type GroupTurnOrigin = "human-explicit" | "controller" | "handoff" | "recovery";
|
|
7
|
+
export type GroupTurnState = "queued" | "running" | "completed" | "failed" | "cancelled";
|
|
8
|
+
export type ConversationRunMode = "explicit";
|
|
9
|
+
export type ConversationRunState = "queued" | "running" | "waiting-human" | "completed" | "failed" | "cancelled" | "indeterminate";
|
|
10
|
+
export type MemberTurnOrigin = "human" | "followup" | "retry" | "recovery";
|
|
11
|
+
export type MemberTurnState = "queued" | "dispatched" | "running" | "completed" | "failed" | "cancelled" | "indeterminate";
|
|
12
|
+
export type PendingDispatchState = "pending" | "claimed" | "completed";
|
|
13
|
+
export interface ConversationRecord {
|
|
14
|
+
id: string;
|
|
15
|
+
kind: ConversationKind;
|
|
16
|
+
title: string;
|
|
17
|
+
description?: string;
|
|
18
|
+
botIds: string[];
|
|
19
|
+
leadBotId?: string;
|
|
20
|
+
/** Bounded AppState lifecycle flag. SQLite conversation_lifecycle is authoritative for dispatch. */
|
|
21
|
+
lifecycle?: ConversationLifecycle;
|
|
22
|
+
createdAt: string;
|
|
23
|
+
updatedAt: string;
|
|
24
|
+
}
|
|
25
|
+
export interface ConversationTopic {
|
|
26
|
+
id: string;
|
|
27
|
+
conversationId: string;
|
|
28
|
+
title: string;
|
|
29
|
+
status: ConversationTopicStatus;
|
|
30
|
+
createdAt: string;
|
|
31
|
+
updatedAt: string;
|
|
32
|
+
}
|
|
33
|
+
export interface ConversationMessage {
|
|
34
|
+
id: string;
|
|
35
|
+
conversationId: string;
|
|
36
|
+
topicId: string;
|
|
37
|
+
seq: number;
|
|
38
|
+
role: ConversationMessageRole;
|
|
39
|
+
senderBotId?: string;
|
|
40
|
+
recipients?: string[];
|
|
41
|
+
content: string;
|
|
42
|
+
replyTo?: string;
|
|
43
|
+
runId?: string;
|
|
44
|
+
createdAt: string;
|
|
45
|
+
sourceTurn?: {
|
|
46
|
+
sessionAlias: string;
|
|
47
|
+
turnId?: string;
|
|
48
|
+
};
|
|
49
|
+
}
|
|
50
|
+
export interface ConversationRun {
|
|
51
|
+
id: string;
|
|
52
|
+
conversationId: string;
|
|
53
|
+
topicId: string;
|
|
54
|
+
requestMessageId: string;
|
|
55
|
+
requestId: string;
|
|
56
|
+
mode: ConversationRunMode;
|
|
57
|
+
state: ConversationRunState;
|
|
58
|
+
completionReason?: string;
|
|
59
|
+
generation: number;
|
|
60
|
+
maxMemberTurns: number;
|
|
61
|
+
consumedMemberTurns: number;
|
|
62
|
+
profileRevision: number;
|
|
63
|
+
profileSnapshot: BotProfileSnapshot;
|
|
64
|
+
createdAt: string;
|
|
65
|
+
startedAt?: string;
|
|
66
|
+
finishedAt?: string;
|
|
67
|
+
}
|
|
68
|
+
export interface MemberTurnRecord {
|
|
69
|
+
id: string;
|
|
70
|
+
runId: string;
|
|
71
|
+
conversationId: string;
|
|
72
|
+
topicId: string;
|
|
73
|
+
botId: string;
|
|
74
|
+
sessionAlias?: string;
|
|
75
|
+
logicalSessionId?: string;
|
|
76
|
+
sourceTurnId?: string;
|
|
77
|
+
queueItemId?: string;
|
|
78
|
+
batch: number;
|
|
79
|
+
attempt: number;
|
|
80
|
+
origin: MemberTurnOrigin;
|
|
81
|
+
state: MemberTurnState;
|
|
82
|
+
triggerMessageIds: string[];
|
|
83
|
+
createdAt: string;
|
|
84
|
+
startedAt?: string;
|
|
85
|
+
finishedAt?: string;
|
|
86
|
+
}
|
|
87
|
+
export interface PendingDispatch {
|
|
88
|
+
id: string;
|
|
89
|
+
runId: string;
|
|
90
|
+
memberTurnId: string;
|
|
91
|
+
generation: number;
|
|
92
|
+
state: PendingDispatchState;
|
|
93
|
+
owner?: string;
|
|
94
|
+
leaseExpiresAt?: string;
|
|
95
|
+
/** Live dispatcher epoch that accepted this work. Matching claim keeps human
|
|
96
|
+
* permission authority; mismatch or revoked epoch is recovery/orchestration. */
|
|
97
|
+
authorityEpoch?: string;
|
|
98
|
+
createdAt: string;
|
|
99
|
+
claimedAt?: string;
|
|
100
|
+
completedAt?: string;
|
|
101
|
+
}
|
|
102
|
+
export interface GroupTurnRecord {
|
|
103
|
+
id: string;
|
|
104
|
+
conversationId: string;
|
|
105
|
+
topicId: string;
|
|
106
|
+
botId: string;
|
|
107
|
+
sessionAlias: string;
|
|
108
|
+
triggerMessageIds: string[];
|
|
109
|
+
origin: GroupTurnOrigin;
|
|
110
|
+
state: GroupTurnState;
|
|
111
|
+
createdAt: string;
|
|
112
|
+
startedAt?: string;
|
|
113
|
+
finishedAt?: string;
|
|
114
|
+
}
|
|
115
|
+
export declare const ACTIVE_RUN_STATES: readonly ConversationRunState[];
|
|
116
|
+
export declare const TERMINAL_RUN_STATES: readonly ConversationRunState[];
|
|
117
|
+
export declare const TERMINAL_MEMBER_STATES: readonly MemberTurnState[];
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import type { AppConfig } from "../config/types";
|
|
2
2
|
import { AsyncMutex } from "../orchestration/async-mutex";
|
|
3
3
|
import type { StateStore } from "../state/state-store";
|
|
4
|
-
import type { AppState, BackgroundResult, LogicalSession, SessionTransportEngine } from "../state/types";
|
|
4
|
+
import type { AppState, BackgroundResult, LogicalSession, LogicalSessionOwner, SessionTransportEngine } from "../state/types";
|
|
5
5
|
import type { SessionResourceLifecyclePublishInput } from "./session-resource-catalog";
|
|
6
6
|
import type { AgentSession, ResolvedSession } from "../transport/types";
|
|
7
7
|
import type { ReapTarget } from "../transport/queue-owner-reaper";
|
|
@@ -125,7 +125,11 @@ export declare class SessionService {
|
|
|
125
125
|
agent: string;
|
|
126
126
|
workspace: string;
|
|
127
127
|
}): SessionTransportEngine;
|
|
128
|
-
createSession(alias: string, agent: string, workspace: string
|
|
128
|
+
createSession(alias: string, agent: string, workspace: string, options?: {
|
|
129
|
+
owner?: LogicalSessionOwner;
|
|
130
|
+
model?: string;
|
|
131
|
+
effort?: string;
|
|
132
|
+
}): Promise<ResolvedSession>;
|
|
129
133
|
/**
|
|
130
134
|
* All currently-known logical sessions resolved to transport sessions, deduped by
|
|
131
135
|
* the composite identity acpx keys its session records on (agent + agent command +
|
|
@@ -250,6 +254,7 @@ export declare class SessionService {
|
|
|
250
254
|
* does not carry (immutable logical_session_id, archived flag).
|
|
251
255
|
*/
|
|
252
256
|
getLogicalSessionRecord(alias: string): LogicalSession | null;
|
|
257
|
+
getLogicalSessionById(logicalSessionId: string): LogicalSession | null;
|
|
253
258
|
/** Read-only view of every persisted logical session record, across all channels. */
|
|
254
259
|
listLogicalSessionRecords(): LogicalSession[];
|
|
255
260
|
setCurrentSessionMode(chatKey: string, modeId: string | undefined): Promise<void>;
|
package/dist/state/types.d.ts
CHANGED
|
@@ -1,7 +1,26 @@
|
|
|
1
|
+
import type { BotProfile, BotRuntimeBinding } from "../bots/bot-types";
|
|
2
|
+
import type { ConversationRecord, ConversationTopic } from "../conversations/conversation-types";
|
|
1
3
|
import { type OrchestrationState } from "../orchestration/orchestration-types";
|
|
2
4
|
import type { ScheduledTaskRecord } from "../scheduled/scheduled-types";
|
|
3
5
|
export type SessionTransportEngine = "cli" | "runtime";
|
|
4
6
|
export type LogicalSessionSource = "xacpx" | "agent-side";
|
|
7
|
+
export interface LogicalSessionOwner {
|
|
8
|
+
kind: "bot-direct" | "group-member" | "group-controller";
|
|
9
|
+
bindingId: string;
|
|
10
|
+
/**
|
|
11
|
+
* Explicit Bot id for scoped bot-direct ownership. Optional on PR2 records
|
|
12
|
+
* that only stored `bindingId` (the legacy deterministic default-Topic id).
|
|
13
|
+
*/
|
|
14
|
+
botId?: string;
|
|
15
|
+
conversationId?: string;
|
|
16
|
+
topicId?: string;
|
|
17
|
+
}
|
|
18
|
+
export declare function createBotDirectOwner(input: {
|
|
19
|
+
bindingId: string;
|
|
20
|
+
botId: string;
|
|
21
|
+
conversationId: string;
|
|
22
|
+
topicId: string;
|
|
23
|
+
}): LogicalSessionOwner;
|
|
5
24
|
export interface NativeSessionCacheEntry {
|
|
6
25
|
session_id: string;
|
|
7
26
|
cwd?: string;
|
|
@@ -59,6 +78,7 @@ export interface LogicalSession {
|
|
|
59
78
|
archived_at?: string;
|
|
60
79
|
created_at: string;
|
|
61
80
|
last_used_at: string;
|
|
81
|
+
owner?: LogicalSessionOwner;
|
|
62
82
|
}
|
|
63
83
|
export interface BackgroundResult {
|
|
64
84
|
text: string;
|
|
@@ -76,5 +96,9 @@ export interface AppState {
|
|
|
76
96
|
native_session_lists: Record<string, NativeSessionListCacheRecord>;
|
|
77
97
|
orchestration: OrchestrationState;
|
|
78
98
|
scheduled_tasks: Record<string, ScheduledTaskRecord>;
|
|
99
|
+
bots: Record<string, BotProfile>;
|
|
100
|
+
conversations: Record<string, ConversationRecord>;
|
|
101
|
+
conversation_topics: Record<string, ConversationTopic>;
|
|
102
|
+
bot_runtime_bindings: Record<string, BotRuntimeBinding>;
|
|
79
103
|
}
|
|
80
104
|
export declare function createEmptyState(): AppState;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@ganglion/xacpx",
|
|
3
|
-
"version": "0.24.
|
|
3
|
+
"version": "0.24.6-beta.0",
|
|
4
4
|
"description": "随时随地通过聊天频道(微信 / 飞书 / 元宝等)远程控制 `acpx` 上的 Claude Code、Codex 等 Agents。",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"acpx",
|
|
@@ -86,12 +86,13 @@
|
|
|
86
86
|
"test:unit": "node ./scripts/run-tests.mjs tests/unit",
|
|
87
87
|
"test:smoke": "node ./scripts/run-tests.mjs tests/smoke",
|
|
88
88
|
"test:compat:acpx": "node ./scripts/run-tests.mjs tests/compat",
|
|
89
|
+
"test:release-boundary": "node ./scripts/release-plan-boundary.mjs",
|
|
89
90
|
"lint:acpx-imports": "node ./scripts/lint-acpx-imports.mjs",
|
|
90
91
|
"smoke:local-install": "node ./scripts/smoke-local-install.mjs"
|
|
91
92
|
},
|
|
92
93
|
"dependencies": {
|
|
93
94
|
"@modelcontextprotocol/sdk": "^1.29.0",
|
|
94
|
-
"acpx": "0.
|
|
95
|
+
"acpx": "0.16.0",
|
|
95
96
|
"node-pty": "^1.1.0",
|
|
96
97
|
"proper-lockfile": "^4.1.2",
|
|
97
98
|
"protobufjs": "^7.5.6",
|