poe-code 3.0.268 → 3.0.270
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/commands/agent.js +3 -31
- package/dist/cli/commands/agent.js.map +1 -1
- package/dist/index.js +297 -294
- package/dist/index.js.map +4 -4
- package/dist/metafile.json +1 -1
- package/dist/providers/gemini-cli.js +10 -8
- package/dist/providers/gemini-cli.js.map +2 -2
- package/dist/providers/poe-agent.js +277 -250
- package/dist/providers/poe-agent.js.map +4 -4
- package/package.json +1 -1
- package/packages/agent-code-review/dist/config.js +15 -1
- package/packages/agent-code-review/dist/document-schemas.js +1 -4
- package/packages/agent-code-review/dist/mcp.js +16 -4
- package/packages/agent-code-review/dist/review-store.js +9 -2
- package/packages/agent-spawn/dist/acp/session-update-converter.d.ts +7 -4
- package/packages/agent-spawn/dist/acp/session-update-converter.js +16 -14
- package/packages/agent-spawn/dist/acp/types.d.ts +15 -3
- package/packages/agent-spawn/dist/index.d.ts +2 -0
- package/packages/agent-spawn/dist/index.js +1 -0
package/package.json
CHANGED
|
@@ -2,6 +2,7 @@ import { lstat, mkdir, readFile, readdir, rename, stat, unlink, writeFile } from
|
|
|
2
2
|
import { homedir } from "node:os";
|
|
3
3
|
import { createConfigStore, defineScope, resolveConfigPath, resolveProjectConfigPath } from "@poe-code/poe-code-config";
|
|
4
4
|
import { codeReviewConfigScope, parseCodeReviewConfigDocument, parseCodeReviewProfileDirectories } from "./config-scope.js";
|
|
5
|
+
import { requireSafeDocumentSegment } from "./document-schemas.js";
|
|
5
6
|
import { hasOwnErrorCode } from "./error-codes.js";
|
|
6
7
|
import { resolveCodeReviewStoreDirectory } from "./review-store.js";
|
|
7
8
|
const poeCoreAgentScope = defineScope("core", {
|
|
@@ -111,7 +112,7 @@ export async function resolveCodeReviewRunOptions(input, configOptions) {
|
|
|
111
112
|
profileDirectories: parseCodeReviewProfileDirectories(inputProfileDirectories ?? configProfileDirectories),
|
|
112
113
|
...(inputProfilePath === undefined ? {} : { profilePath: inputProfilePath }),
|
|
113
114
|
...(inputPromptPath === undefined ? {} : { promptPath: inputPromptPath }),
|
|
114
|
-
...(inputProfiles === undefined ? {} : { profiles: inputProfiles }),
|
|
115
|
+
...(inputProfiles === undefined ? {} : { profiles: requireProfileFilters(inputProfiles) }),
|
|
115
116
|
...(inputAdditionalFeedback === undefined
|
|
116
117
|
? {}
|
|
117
118
|
: { additionalFeedback: inputAdditionalFeedback })
|
|
@@ -165,6 +166,19 @@ function requireNonEmptyString(value, field) {
|
|
|
165
166
|
}
|
|
166
167
|
return normalized;
|
|
167
168
|
}
|
|
169
|
+
function requireProfileFilters(value) {
|
|
170
|
+
if (!Array.isArray(value)) {
|
|
171
|
+
throw new Error("profiles must be an array of safe profile names.");
|
|
172
|
+
}
|
|
173
|
+
return value.map((profile) => {
|
|
174
|
+
try {
|
|
175
|
+
return requireSafeDocumentSegment(profile, "profiles");
|
|
176
|
+
}
|
|
177
|
+
catch {
|
|
178
|
+
throw new Error("profiles must be an array of safe profile names.");
|
|
179
|
+
}
|
|
180
|
+
});
|
|
181
|
+
}
|
|
168
182
|
function isMissingFileError(error) {
|
|
169
183
|
return hasOwnErrorCode(error, "ENOENT");
|
|
170
184
|
}
|
|
@@ -8,7 +8,7 @@ const CODE_REVIEW_PROMPT_ROLES = [
|
|
|
8
8
|
];
|
|
9
9
|
const FRONTMATTER_RE = /^---\r?\n([\s\S]*?)\r?\n---(?:\r?\n|$)([\s\S]*)$/;
|
|
10
10
|
const SAFE_SEGMENT_RE = /^[A-Za-z0-9._-]+$/;
|
|
11
|
-
const SAFE_GITHUB_ACTOR_RE = /^[A-Za-z0-9](?:[A-Za-z0-9-]{0,
|
|
11
|
+
const SAFE_GITHUB_ACTOR_RE = /^[A-Za-z0-9](?:[A-Za-z0-9-]{0,37}[A-Za-z0-9])?$/;
|
|
12
12
|
export function requireSafeDocumentSegment(value, field) {
|
|
13
13
|
if (typeof value !== "string" ||
|
|
14
14
|
value.trim() !== value ||
|
|
@@ -179,9 +179,6 @@ export function serializeCodeReviewIngestSource(source, filePath = "code-review
|
|
|
179
179
|
function parseOptionalFrontmatter(content, filePath) {
|
|
180
180
|
const match = content.match(FRONTMATTER_RE);
|
|
181
181
|
if (!match) {
|
|
182
|
-
if (/^---\r?\n/.test(content)) {
|
|
183
|
-
throw new Error(`${filePath}: frontmatter is missing a closing --- delimiter.`);
|
|
184
|
-
}
|
|
185
182
|
return { body: content };
|
|
186
183
|
}
|
|
187
184
|
try {
|
|
@@ -11,11 +11,17 @@ import { buildCodeReviewReviewerPrompt } from "./prompt-builders.js";
|
|
|
11
11
|
export const CODE_REVIEW_AGENT_MCP_ROLES = ["agent", "orchestrator", "subagent"];
|
|
12
12
|
const inlineCommentSchema = S.Object({
|
|
13
13
|
path: S.String({ description: "Repository-relative path in the PR diff." }),
|
|
14
|
-
line: S.Number({
|
|
14
|
+
line: S.Number({
|
|
15
|
+
description: "Right-side line number in the PR diff.",
|
|
16
|
+
jsonType: "integer",
|
|
17
|
+
minimum: 1
|
|
18
|
+
}),
|
|
15
19
|
body: S.String({ description: "Inline review comment body." })
|
|
16
20
|
});
|
|
17
21
|
const inlineCommentIndexSchema = S.Number({
|
|
18
|
-
description: "Zero-based merged review inline comment index."
|
|
22
|
+
description: "Zero-based merged review inline comment index.",
|
|
23
|
+
jsonType: "integer",
|
|
24
|
+
minimum: 0
|
|
19
25
|
});
|
|
20
26
|
const prParam = S.String({ description: "GitHub pull request URL." });
|
|
21
27
|
export function parseCodeReviewAgentMcpArgs(argv) {
|
|
@@ -140,7 +146,9 @@ export function createCodeReviewAgentMcpGroup(context, dependencies = {}) {
|
|
|
140
146
|
handler: async ({ params }) => {
|
|
141
147
|
const pr = canonicalPullRequestUrl(params.pr);
|
|
142
148
|
const draft = validateDraft(params);
|
|
143
|
-
const currentState =
|
|
149
|
+
const currentState = context.role === "orchestrator"
|
|
150
|
+
? await ensureState(store, context, pr)
|
|
151
|
+
: await requireState(store, context, pr);
|
|
144
152
|
if (context.role === "orchestrator") {
|
|
145
153
|
const unfinishedProfiles = Object.values(currentState.subagents)
|
|
146
154
|
.filter(({ status }) => status === "pending" || status === "running")
|
|
@@ -342,7 +350,11 @@ export function createCodeReviewAgentMcpGroup(context, dependencies = {}) {
|
|
|
342
350
|
pr: prParam,
|
|
343
351
|
index: inlineCommentIndexSchema,
|
|
344
352
|
path: S.String({ description: "Repository-relative path in the PR diff." }),
|
|
345
|
-
line: S.Number({
|
|
353
|
+
line: S.Number({
|
|
354
|
+
description: "Right-side line number in the PR diff.",
|
|
355
|
+
jsonType: "integer",
|
|
356
|
+
minimum: 1
|
|
357
|
+
}),
|
|
346
358
|
body: S.String({ description: "Inline review comment body." })
|
|
347
359
|
}),
|
|
348
360
|
handler: async ({ params }) => {
|
|
@@ -436,8 +436,8 @@ async function withFileLock(lockPath, lockTimeoutMs, operation) {
|
|
|
436
436
|
}
|
|
437
437
|
async function isStaleLock(lockPath, lockTimeoutMs) {
|
|
438
438
|
try {
|
|
439
|
-
const ownerPid =
|
|
440
|
-
if (
|
|
439
|
+
const ownerPid = parseLockOwnerPid((await readFile(lockPath, "utf8")).trim());
|
|
440
|
+
if (ownerPid !== undefined) {
|
|
441
441
|
return !isRunningProcess(ownerPid);
|
|
442
442
|
}
|
|
443
443
|
return Date.now() - (await stat(lockPath)).mtimeMs >= lockTimeoutMs;
|
|
@@ -449,6 +449,13 @@ async function isStaleLock(lockPath, lockTimeoutMs) {
|
|
|
449
449
|
throw error;
|
|
450
450
|
}
|
|
451
451
|
}
|
|
452
|
+
function parseLockOwnerPid(value) {
|
|
453
|
+
const processId = Number(value);
|
|
454
|
+
if (!Number.isSafeInteger(processId) || processId <= 0) {
|
|
455
|
+
return undefined;
|
|
456
|
+
}
|
|
457
|
+
return String(processId) === value ? processId : undefined;
|
|
458
|
+
}
|
|
452
459
|
function isRunningProcess(processId) {
|
|
453
460
|
try {
|
|
454
461
|
process.kill(processId, 0);
|
|
@@ -1,10 +1,13 @@
|
|
|
1
|
-
import type { SessionUpdate, ToolKind } from "../../../poe-acp-client/dist/index.js";
|
|
2
|
-
import type { AcpEvent } from "./types.js";
|
|
1
|
+
import type { SessionUpdate as AcpClientSessionUpdate, ToolKind as AcpClientToolKind } from "../../../poe-acp-client/dist/index.js";
|
|
2
|
+
import type { AcpEvent, SessionUpdate as LegacySessionUpdate, ToolKind as LegacyToolKind } from "./types.js";
|
|
3
|
+
type ConvertibleSessionUpdate = AcpClientSessionUpdate | LegacySessionUpdate;
|
|
4
|
+
type ConvertibleToolKind = AcpClientToolKind | LegacyToolKind;
|
|
3
5
|
export interface ToolRenderState {
|
|
4
6
|
startedToolCalls: Set<string>;
|
|
5
7
|
toolCallKinds: Map<string, string>;
|
|
6
8
|
toolCallTitles: Map<string, string>;
|
|
7
9
|
}
|
|
8
10
|
export declare function createToolRenderState(): ToolRenderState;
|
|
9
|
-
export declare function toRenderKind(kind:
|
|
10
|
-
export declare function sessionUpdateToEvents(update:
|
|
11
|
+
export declare function toRenderKind(kind: ConvertibleToolKind | undefined | null): string;
|
|
12
|
+
export declare function sessionUpdateToEvents(update: ConvertibleSessionUpdate, state: ToolRenderState): AcpEvent[];
|
|
13
|
+
export {};
|
|
@@ -2,13 +2,13 @@ export function createToolRenderState() {
|
|
|
2
2
|
return {
|
|
3
3
|
startedToolCalls: new Set(),
|
|
4
4
|
toolCallKinds: new Map(),
|
|
5
|
-
toolCallTitles: new Map()
|
|
5
|
+
toolCallTitles: new Map()
|
|
6
6
|
};
|
|
7
7
|
}
|
|
8
8
|
export function toRenderKind(kind) {
|
|
9
9
|
if (kind === "execute")
|
|
10
10
|
return "exec";
|
|
11
|
-
if (kind === "write")
|
|
11
|
+
if (kind === "write" || kind === "edit")
|
|
12
12
|
return "edit";
|
|
13
13
|
if (kind === "read")
|
|
14
14
|
return "read";
|
|
@@ -60,7 +60,7 @@ export function sessionUpdateToEvents(update, state) {
|
|
|
60
60
|
const usage = {
|
|
61
61
|
event: "usage",
|
|
62
62
|
inputTokens,
|
|
63
|
-
outputTokens
|
|
63
|
+
outputTokens
|
|
64
64
|
};
|
|
65
65
|
if (cachedTokens > 0) {
|
|
66
66
|
usage.cachedTokens = cachedTokens;
|
|
@@ -79,31 +79,33 @@ export function sessionUpdateToEvents(update, state) {
|
|
|
79
79
|
return [];
|
|
80
80
|
}
|
|
81
81
|
state.startedToolCalls.add(update.toolCallId);
|
|
82
|
-
return [
|
|
82
|
+
return [
|
|
83
|
+
{
|
|
83
84
|
event: "tool_start",
|
|
84
85
|
kind: renderKind,
|
|
85
86
|
title,
|
|
86
|
-
id: update.toolCallId
|
|
87
|
-
}
|
|
87
|
+
id: update.toolCallId
|
|
88
|
+
}
|
|
89
|
+
];
|
|
88
90
|
}
|
|
89
91
|
if (update.sessionUpdate === "tool_call_update") {
|
|
90
|
-
const renderKind =
|
|
91
|
-
|
|
92
|
-
|
|
92
|
+
const renderKind = (update.kind == null ? undefined : toRenderKind(update.kind)) ||
|
|
93
|
+
state.toolCallKinds.get(update.toolCallId) ||
|
|
94
|
+
"other";
|
|
93
95
|
state.toolCallKinds.set(update.toolCallId, renderKind);
|
|
94
96
|
const events = [];
|
|
95
97
|
const toolTitle = toToolTitle(state.toolCallTitles.get(update.toolCallId) ?? update.toolCallId, update.locations);
|
|
96
98
|
state.toolCallTitles.set(update.toolCallId, toolTitle);
|
|
97
99
|
const status = update.status;
|
|
98
|
-
const shouldStart = !state.startedToolCalls.has(update.toolCallId)
|
|
99
|
-
|
|
100
|
+
const shouldStart = !state.startedToolCalls.has(update.toolCallId) &&
|
|
101
|
+
(status === "pending" || status === "in_progress");
|
|
100
102
|
if (shouldStart) {
|
|
101
103
|
state.startedToolCalls.add(update.toolCallId);
|
|
102
104
|
events.push({
|
|
103
105
|
event: "tool_start",
|
|
104
106
|
kind: renderKind,
|
|
105
107
|
title: toolTitle,
|
|
106
|
-
id: update.toolCallId
|
|
108
|
+
id: update.toolCallId
|
|
107
109
|
});
|
|
108
110
|
}
|
|
109
111
|
if (status === "completed" || status === "failed" || status === "cancelled") {
|
|
@@ -113,14 +115,14 @@ export function sessionUpdateToEvents(update, state) {
|
|
|
113
115
|
event: "tool_start",
|
|
114
116
|
kind: renderKind,
|
|
115
117
|
title: toolTitle,
|
|
116
|
-
id: update.toolCallId
|
|
118
|
+
id: update.toolCallId
|
|
117
119
|
});
|
|
118
120
|
}
|
|
119
121
|
events.push({
|
|
120
122
|
event: "tool_complete",
|
|
121
123
|
kind: renderKind,
|
|
122
124
|
path: extractToolOutputText(update),
|
|
123
|
-
id: update.toolCallId
|
|
125
|
+
id: update.toolCallId
|
|
124
126
|
});
|
|
125
127
|
}
|
|
126
128
|
return events;
|
|
@@ -18,7 +18,7 @@
|
|
|
18
18
|
*/
|
|
19
19
|
export type ToolKind = "read" | "edit" | "delete" | "move" | "search" | "execute" | "think" | "fetch" | "switch_mode" | "other";
|
|
20
20
|
/** ACP-compatible type - @see https://agentclientprotocol.com/ - no package dependency, structural compatibility only */
|
|
21
|
-
export type ToolCallStatus = "pending" | "in_progress" | "completed" | "failed";
|
|
21
|
+
export type ToolCallStatus = "pending" | "in_progress" | "completed" | "failed" | "cancelled";
|
|
22
22
|
/** ACP-compatible type - @see https://agentclientprotocol.com/ - no package dependency, structural compatibility only */
|
|
23
23
|
export interface ContentChunk {
|
|
24
24
|
type: "text";
|
|
@@ -39,9 +39,12 @@ export interface ToolCall {
|
|
|
39
39
|
sessionUpdate: "tool_call";
|
|
40
40
|
toolCallId: string;
|
|
41
41
|
title: string;
|
|
42
|
+
content?: ToolCallContent[];
|
|
42
43
|
kind?: ToolKind;
|
|
44
|
+
locations?: ToolCallLocation[];
|
|
43
45
|
status?: ToolCallStatus;
|
|
44
46
|
rawInput?: unknown;
|
|
47
|
+
rawOutput?: unknown;
|
|
45
48
|
_meta?: Record<string, unknown>;
|
|
46
49
|
}
|
|
47
50
|
/** ACP-compatible type - @see https://agentclientprotocol.com/ - no package dependency, structural compatibility only */
|
|
@@ -54,13 +57,22 @@ export type ToolCallContent = {
|
|
|
54
57
|
data: string;
|
|
55
58
|
};
|
|
56
59
|
/** ACP-compatible type - @see https://agentclientprotocol.com/ - no package dependency, structural compatibility only */
|
|
60
|
+
export interface ToolCallLocation {
|
|
61
|
+
path: string;
|
|
62
|
+
lineNumber?: number | null;
|
|
63
|
+
_meta?: Record<string, unknown>;
|
|
64
|
+
}
|
|
65
|
+
/** ACP-compatible type - @see https://agentclientprotocol.com/ - no package dependency, structural compatibility only */
|
|
57
66
|
export interface ToolCallUpdate {
|
|
58
67
|
sessionUpdate: "tool_call_update";
|
|
59
68
|
toolCallId: string;
|
|
60
69
|
kind?: ToolKind;
|
|
61
|
-
status?: ToolCallStatus;
|
|
70
|
+
status?: ToolCallStatus | null;
|
|
62
71
|
rawOutput?: unknown;
|
|
63
|
-
|
|
72
|
+
rawInput?: unknown;
|
|
73
|
+
content?: ToolCallContent[] | null;
|
|
74
|
+
locations?: ToolCallLocation[] | null;
|
|
75
|
+
title?: string | null;
|
|
64
76
|
_meta?: Record<string, unknown>;
|
|
65
77
|
}
|
|
66
78
|
/** ACP-compatible type - @see https://agentclientprotocol.com/ - no package dependency, structural compatibility only */
|
|
@@ -17,6 +17,8 @@ export { spawnInteractive } from "./spawn-interactive.js";
|
|
|
17
17
|
export { spawnAutonomous } from "./autonomous.js";
|
|
18
18
|
export type { AutonomousOptions, StreamingSpawnFn, StreamingSpawnReturn } from "./autonomous.js";
|
|
19
19
|
export { renderAcpEvent, renderAcpStream, renderSessionUpdateStream } from "./acp/renderer.js";
|
|
20
|
+
export { createToolRenderState, sessionUpdateToEvents } from "./acp/session-update-converter.js";
|
|
21
|
+
export type { ToolRenderState } from "./acp/session-update-converter.js";
|
|
20
22
|
export type { LogEntry, MalformedSpawnLogRecord, ReadSpawnLogOptions } from "./acp/replay.js";
|
|
21
23
|
export { findLatestLog, listSpawnLogs, pickRandomLog, readSpawnLog, replaySpawnLog } from "./acp/replay.js";
|
|
22
24
|
export type { SpawnStreamingOptions, SpawnStreamingResult } from "./acp/spawn.js";
|
|
@@ -14,6 +14,7 @@ export { createSpawnParallel, SpawnParallelError } from "./parallel.js";
|
|
|
14
14
|
export { spawnInteractive } from "./spawn-interactive.js";
|
|
15
15
|
export { spawnAutonomous } from "./autonomous.js";
|
|
16
16
|
export { renderAcpEvent, renderAcpStream, renderSessionUpdateStream } from "./acp/renderer.js";
|
|
17
|
+
export { createToolRenderState, sessionUpdateToEvents } from "./acp/session-update-converter.js";
|
|
17
18
|
export { findLatestLog, listSpawnLogs, pickRandomLog, readSpawnLog, replaySpawnLog } from "./acp/replay.js";
|
|
18
19
|
export { spawnStreaming } from "./acp/spawn.js";
|
|
19
20
|
export { spawnAcp } from "./acp/spawn-acp.js";
|