feat: pending-finish proposals and QQ image input
Proposal semantics: worker results no longer distinguish success/fail; only an explicit finish settles a pending proposal. Pending owner input follows up by resuming the original worker session. Dirty pending blocks start_next globally; clean pending only blocks its owner. QQ adapter now downloads image attachments and passes them as ACP image content blocks; video/file attachments degrade to link text.
This commit is contained in:
+5
-3
@@ -4,7 +4,7 @@ import fs from "node:fs";
|
||||
import type { AcpConfig, PermissionPolicy } from "../config.js";
|
||||
import type { WorkerProcessGroup } from "../core/proposal-store.js";
|
||||
import type { ResolvedBot } from "../roles/role-registry.js";
|
||||
import { AcpClient, type SafeActivityCategory } from "./client.js";
|
||||
import { AcpClient, type AcpPromptContent, type SafeActivityCategory } from "./client.js";
|
||||
|
||||
export class AcpSessionRestoreError extends Error {}
|
||||
|
||||
@@ -35,6 +35,7 @@ export class AcpWorker {
|
||||
nativeSessionId?: string;
|
||||
processGroup?: WorkerProcessGroup;
|
||||
isolationViolated = false;
|
||||
supportsImages = false;
|
||||
lastUsedAt = Date.now();
|
||||
turnStartedAt?: number;
|
||||
lastActivityAt?: number;
|
||||
@@ -94,6 +95,7 @@ export class AcpWorker {
|
||||
this.processGroup = { pgid: this.child.pid, token: processToken };
|
||||
await this.options.onSpawn?.(this.processGroup);
|
||||
const initialized = await this.client.initialize();
|
||||
this.supportsImages = this.client.supportsImageInput();
|
||||
if (this.kind === "assistant" && !this.options.allowUnverifiedAssistantAgent && initialized.agentInfo?.name !== "Kimi Code CLI") {
|
||||
throw new Error("Assistant sessions require Kimi Code ACP with execution-layer no-tool profiles");
|
||||
}
|
||||
@@ -111,7 +113,7 @@ export class AcpWorker {
|
||||
}
|
||||
}
|
||||
|
||||
async prompt(text: string, phase: Exclude<AcpWorkerPhase, "idle"> = "processing"): Promise<string> {
|
||||
async prompt(input: string | AcpPromptContent[], phase: Exclude<AcpWorkerPhase, "idle"> = "processing"): Promise<string> {
|
||||
if (!this.client || !this.nativeSessionId || this.exited) throw new Error("ACP worker is not available");
|
||||
if (this.inFlight) throw new Error("ACP worker already has an in-flight turn");
|
||||
const now = Date.now();
|
||||
@@ -131,7 +133,7 @@ export class AcpWorker {
|
||||
}, this.config.promptTimeoutMs);
|
||||
});
|
||||
try {
|
||||
const result = await Promise.race([this.client.prompt(text, this.abort.signal), timeoutPromise]);
|
||||
const result = await Promise.race([this.client.prompt(input, this.abort.signal), timeoutPromise]);
|
||||
if (this.kind === "assistant") await this.client.settleIsolation();
|
||||
return result;
|
||||
} finally {
|
||||
|
||||
Reference in New Issue
Block a user