@nghyane/arcane 0.1.7 → 0.1.10
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/CHANGELOG.md +6 -0
- package/package.json +6 -6
- package/src/cli/update-cli.ts +2 -1
- package/src/cli.ts +2 -1
- package/src/config/settings-schema.ts +0 -10
- package/src/debug/system-info.ts +2 -1
- package/src/discovery/helpers.ts +1 -6
- package/src/index.ts +3 -1
- package/src/main.ts +2 -1
- package/src/memories/index.ts +3 -3
- package/src/modes/components/settings-defs.ts +0 -8
- package/src/patch/applicator.ts +12 -4
- package/src/prompts/agents/task.md +1 -1
- package/src/prompts/system/subagent-system-prompt.md +2 -14
- package/src/prompts/system/system-prompt.md +12 -14
- package/src/prompts/tools/task.md +49 -178
- package/src/prompts/tools/todo-write.md +4 -4
- package/src/sdk.ts +15 -16
- package/src/session/session-manager.ts +1 -3
- package/src/task/executor.ts +2 -2
- package/src/task/index.ts +5 -5
- package/src/task/types.ts +7 -20
- package/src/tools/index.ts +16 -33
- package/src/tools/subagent-tool.ts +5 -5
- package/src/tools/todo-write.ts +0 -37
- package/src/version.ts +3 -0
- package/src/prompts/system/subagent-submit-reminder.md +0 -11
- package/src/tools/jtd-to-json-schema.ts +0 -247
- package/src/tools/submit-result.ts +0 -152
|
@@ -1,152 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Submit result tool for structured subagent output.
|
|
3
|
-
*
|
|
4
|
-
* Subagents must call this tool to finish and return structured JSON output.
|
|
5
|
-
*/
|
|
6
|
-
import type { AgentTool, AgentToolContext, AgentToolResult, AgentToolUpdateCallback } from "@nghyane/arcane-agent";
|
|
7
|
-
import { StringEnum } from "@nghyane/arcane-ai";
|
|
8
|
-
import type { Static, TObject } from "@sinclair/typebox";
|
|
9
|
-
import { Type } from "@sinclair/typebox";
|
|
10
|
-
import Ajv, { type ErrorObject, type ValidateFunction } from "ajv";
|
|
11
|
-
import { subprocessToolRegistry } from "../task/subprocess-tool-registry";
|
|
12
|
-
import type { ToolSession } from ".";
|
|
13
|
-
import { jtdToJsonSchema } from "./jtd-to-json-schema";
|
|
14
|
-
|
|
15
|
-
export interface SubmitResultDetails {
|
|
16
|
-
data: unknown;
|
|
17
|
-
status: "success" | "aborted";
|
|
18
|
-
error?: string;
|
|
19
|
-
}
|
|
20
|
-
|
|
21
|
-
const ajv = new Ajv({ allErrors: true, strict: false });
|
|
22
|
-
|
|
23
|
-
function normalizeSchema(schema: unknown): { normalized?: unknown; error?: string } {
|
|
24
|
-
if (schema === undefined || schema === null) return {};
|
|
25
|
-
if (typeof schema === "string") {
|
|
26
|
-
try {
|
|
27
|
-
return { normalized: JSON.parse(schema) };
|
|
28
|
-
} catch (err) {
|
|
29
|
-
return { error: err instanceof Error ? err.message : String(err) };
|
|
30
|
-
}
|
|
31
|
-
}
|
|
32
|
-
return { normalized: schema };
|
|
33
|
-
}
|
|
34
|
-
|
|
35
|
-
function formatSchema(schema: unknown): string {
|
|
36
|
-
if (schema === undefined) return "No schema provided.";
|
|
37
|
-
if (typeof schema === "string") return schema;
|
|
38
|
-
try {
|
|
39
|
-
return JSON.stringify(schema, null, 2);
|
|
40
|
-
} catch {
|
|
41
|
-
return "[unserializable schema]";
|
|
42
|
-
}
|
|
43
|
-
}
|
|
44
|
-
|
|
45
|
-
function formatAjvErrors(errors: ErrorObject[] | null | undefined): string {
|
|
46
|
-
if (!errors || errors.length === 0) return "Unknown schema validation error.";
|
|
47
|
-
return errors
|
|
48
|
-
.map(err => {
|
|
49
|
-
const path = err.instancePath ? `${err.instancePath}: ` : "";
|
|
50
|
-
return `${path}${err.message ?? "invalid"}`;
|
|
51
|
-
})
|
|
52
|
-
.join("; ");
|
|
53
|
-
}
|
|
54
|
-
|
|
55
|
-
export class SubmitResultTool implements AgentTool<TObject, SubmitResultDetails> {
|
|
56
|
-
readonly name = "submit_result";
|
|
57
|
-
readonly label = "Submit Result";
|
|
58
|
-
readonly description =
|
|
59
|
-
"Finish the task with structured JSON output. Call exactly once at the end of the task.\n\n" +
|
|
60
|
-
"If you cannot complete the task, call with status='aborted' and an error message.";
|
|
61
|
-
readonly parameters: TObject;
|
|
62
|
-
|
|
63
|
-
readonly #validate?: ValidateFunction;
|
|
64
|
-
readonly #schemaError?: string;
|
|
65
|
-
|
|
66
|
-
constructor(session: ToolSession) {
|
|
67
|
-
const schemaResult = normalizeSchema(session.outputSchema);
|
|
68
|
-
// Convert JTD to JSON Schema if needed (auto-detected)
|
|
69
|
-
const normalizedSchema =
|
|
70
|
-
schemaResult.normalized !== undefined ? jtdToJsonSchema(schemaResult.normalized) : undefined;
|
|
71
|
-
let schemaError = schemaResult.error;
|
|
72
|
-
|
|
73
|
-
if (normalizedSchema !== undefined && !schemaError) {
|
|
74
|
-
try {
|
|
75
|
-
this.#validate = ajv.compile(normalizedSchema as any);
|
|
76
|
-
} catch (err) {
|
|
77
|
-
schemaError = err instanceof Error ? err.message : String(err);
|
|
78
|
-
}
|
|
79
|
-
}
|
|
80
|
-
|
|
81
|
-
this.#schemaError = schemaError;
|
|
82
|
-
|
|
83
|
-
const schemaHint = formatSchema(normalizedSchema ?? session.outputSchema);
|
|
84
|
-
|
|
85
|
-
// Use actual schema if provided, otherwise fall back to Type.Any
|
|
86
|
-
// Merge description into the JSON schema for better tool documentation
|
|
87
|
-
const dataSchema = normalizedSchema
|
|
88
|
-
? Type.Unsafe({
|
|
89
|
-
...(normalizedSchema as object),
|
|
90
|
-
description: `Structured output matching the schema:\n${schemaHint}`,
|
|
91
|
-
})
|
|
92
|
-
: Type.Any({ description: "Structured JSON output (no schema specified)" });
|
|
93
|
-
|
|
94
|
-
this.parameters = Type.Object({
|
|
95
|
-
data: Type.Optional(dataSchema),
|
|
96
|
-
status: Type.Optional(
|
|
97
|
-
StringEnum(["success", "aborted"], {
|
|
98
|
-
description: "Use 'aborted' if the task cannot be completed, defaults to 'success'",
|
|
99
|
-
}),
|
|
100
|
-
),
|
|
101
|
-
error: Type.Optional(Type.String({ description: "Error message when status is 'aborted'" })),
|
|
102
|
-
});
|
|
103
|
-
}
|
|
104
|
-
|
|
105
|
-
async execute(
|
|
106
|
-
_toolCallId: string,
|
|
107
|
-
params: Static<TObject>,
|
|
108
|
-
_signal?: AbortSignal,
|
|
109
|
-
_onUpdate?: AgentToolUpdateCallback<SubmitResultDetails>,
|
|
110
|
-
_context?: AgentToolContext,
|
|
111
|
-
): Promise<AgentToolResult<SubmitResultDetails>> {
|
|
112
|
-
const status = (params.status ?? "success") as "success" | "aborted";
|
|
113
|
-
|
|
114
|
-
// Skip validation when aborting - data is optional for aborts
|
|
115
|
-
if (status === "success") {
|
|
116
|
-
if (params.data === undefined || params.data === null) {
|
|
117
|
-
throw new Error("data is required when status is 'success' (got null/undefined)");
|
|
118
|
-
}
|
|
119
|
-
if (this.#schemaError) {
|
|
120
|
-
throw new Error(`Invalid output schema: ${this.#schemaError}`);
|
|
121
|
-
}
|
|
122
|
-
if (this.#validate && !this.#validate(params.data)) {
|
|
123
|
-
throw new Error(`Output does not match schema: ${formatAjvErrors(this.#validate.errors)}`);
|
|
124
|
-
}
|
|
125
|
-
}
|
|
126
|
-
|
|
127
|
-
const responseText =
|
|
128
|
-
status === "aborted" ? `Task aborted: ${params.error || "No reason provided"}` : "Result submitted.";
|
|
129
|
-
|
|
130
|
-
return {
|
|
131
|
-
content: [{ type: "text", text: responseText }],
|
|
132
|
-
details: { data: params.data, status, error: params.error as string | undefined },
|
|
133
|
-
};
|
|
134
|
-
}
|
|
135
|
-
}
|
|
136
|
-
|
|
137
|
-
// Register subprocess tool handler for extraction + termination.
|
|
138
|
-
subprocessToolRegistry.register<SubmitResultDetails>("submit_result", {
|
|
139
|
-
extractData: event => {
|
|
140
|
-
const details = event.result?.details;
|
|
141
|
-
if (!details || typeof details !== "object") return undefined;
|
|
142
|
-
const record = details as Record<string, unknown>;
|
|
143
|
-
const status = record.status;
|
|
144
|
-
if (status !== "success" && status !== "aborted") return undefined;
|
|
145
|
-
return {
|
|
146
|
-
data: record.data,
|
|
147
|
-
status,
|
|
148
|
-
error: typeof record.error === "string" ? record.error : undefined,
|
|
149
|
-
};
|
|
150
|
-
},
|
|
151
|
-
shouldTerminate: event => !event.isError,
|
|
152
|
-
});
|