@mawaru/sdk 0.11.0 → 0.14.1
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/_schemas/ai-manifest.test.ts +54 -59
- package/_schemas/ai-manifest.ts +38 -23
- package/_schemas/duplicate-selection.test.ts +235 -0
- package/_schemas/duplicate-selection.ts +48 -0
- package/_schemas/extract-component.test.ts +51 -2
- package/_schemas/extract-component.ts +4 -2
- package/_schemas/graph.test.ts +105 -86
- package/_schemas/graph.ts +20 -77
- package/_schemas/node.ts +4 -0
- package/_schemas/port-spec.test.ts +194 -113
- package/_schemas/port-spec.ts +95 -107
- package/dist/_cli/credentials.d.ts +14 -0
- package/dist/_cli/credentials.js +81 -0
- package/dist/_cli/login.d.ts +5 -0
- package/dist/_cli/login.js +82 -0
- package/dist/_cli/resumeSession.d.ts +21 -0
- package/dist/_cli/resumeSession.js +125 -0
- package/dist/_cli/sessionCommand.d.ts +3 -0
- package/dist/_cli/sessionCommand.js +55 -0
- package/dist/_schemas/ai-manifest.d.ts +12 -1
- package/dist/_schemas/ai-manifest.js +35 -20
- package/dist/_schemas/duplicate-selection.d.ts +12 -0
- package/dist/_schemas/duplicate-selection.js +34 -0
- package/dist/_schemas/extract-component.js +4 -2
- package/dist/_schemas/graph.d.ts +14 -12
- package/dist/_schemas/graph.js +21 -60
- package/dist/_schemas/hook-manifest.d.ts +2 -2
- package/dist/_schemas/node.d.ts +3 -2
- package/dist/_schemas/node.js +4 -0
- package/dist/_schemas/port-spec.d.ts +11 -6
- package/dist/_schemas/port-spec.js +72 -97
- package/dist/cli.js +50 -5
- package/dist/index.d.ts +1 -0
- package/dist/index.js +1 -0
- package/dist/init.js +1 -1
- package/dist/typegen.js +6 -6
- package/docs/development.md +5 -1
- package/index.ts +1 -0
- package/package.json +11 -18
- package/skills/create-loop/SKILL.md +1 -1
- package/templates/CLAUDE.md +1 -1
- package/templates/echo/main.ts +1 -1
- package/templates/mawaru-runner.yml +1 -1
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
import { createInterface } from "node:readline/promises";
|
|
2
|
+
import { requireCredentials } from "./credentials.js";
|
|
3
|
+
import { downloadTranscript, fetchTranscriptRef, parseStepUrl, placeTranscript, recordedCwds, spawnClaudeResume, } from "./resumeSession.js";
|
|
4
|
+
const confirm = async (question) => {
|
|
5
|
+
const rl = createInterface({ input: process.stdin, output: process.stdout });
|
|
6
|
+
try {
|
|
7
|
+
const answer = await rl.question(`${question} [y/N] `);
|
|
8
|
+
return /^y(es)?$/i.test(answer.trim());
|
|
9
|
+
}
|
|
10
|
+
finally {
|
|
11
|
+
rl.close();
|
|
12
|
+
}
|
|
13
|
+
};
|
|
14
|
+
// `mawaru session resume <step URL> [--yes]`
|
|
15
|
+
//
|
|
16
|
+
// 取得 → 作業ディレクトリの確認 → 配置 → `claude --resume`。
|
|
17
|
+
// **どこに cd すべきかは mawaru には分からない**(AI ノードの実行 repo と、エージェントが
|
|
18
|
+
// 実際に触った repo は別物で、後者は setup.sh が workspace/ 配下に clone した対象 repo)。
|
|
19
|
+
// なので推定せず、記録された cwd をそのまま見せて人間に判断させる
|
|
20
|
+
export const runSessionResume = async (stepUrl, options) => {
|
|
21
|
+
if (!stepUrl) {
|
|
22
|
+
console.error("使い方: mawaru session resume <step URL> [--yes]\n" +
|
|
23
|
+
"run 詳細の AI ノードにあるコピーボタンで URL を取得できます。");
|
|
24
|
+
return 1;
|
|
25
|
+
}
|
|
26
|
+
// URL の誤りは通信より先に落とす
|
|
27
|
+
const ref = parseStepUrl(stepUrl);
|
|
28
|
+
const credentials = requireCredentials();
|
|
29
|
+
const transcriptRef = await fetchTranscriptRef(credentials, ref);
|
|
30
|
+
const transcript = await downloadTranscript(transcriptRef.url);
|
|
31
|
+
console.log(`取得: セッション ${transcriptRef.session_id}`);
|
|
32
|
+
if (transcriptRef.redacted) {
|
|
33
|
+
console.log(`(退避時に secret を ${transcriptRef.redacted} 箇所マスクしています)`);
|
|
34
|
+
}
|
|
35
|
+
const { all, last } = recordedCwds(transcript);
|
|
36
|
+
const cwd = process.cwd();
|
|
37
|
+
if (all.length > 0) {
|
|
38
|
+
console.log("このセッションの作業ディレクトリ:");
|
|
39
|
+
for (const dir of all) {
|
|
40
|
+
console.log(` ${dir}${dir === last ? "(最後に居た場所)" : ""}`);
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
console.log(`現在地:\n ${cwd}`);
|
|
44
|
+
if (!all.includes(cwd)) {
|
|
45
|
+
console.log("※ 記録された作業ディレクトリとは違います。記録上の絶対パスはここでは解決しません" +
|
|
46
|
+
"(エージェントは読めないパスに当たれば自分で見つけ直します)。");
|
|
47
|
+
}
|
|
48
|
+
if (!options.yes && !(await confirm("続けますか?"))) {
|
|
49
|
+
console.log("中止しました。");
|
|
50
|
+
return 1;
|
|
51
|
+
}
|
|
52
|
+
const file = placeTranscript(cwd, transcriptRef.session_id, transcript);
|
|
53
|
+
console.log(`配置: ${file}\n再開します…`);
|
|
54
|
+
return await spawnClaudeResume(transcriptRef.session_id);
|
|
55
|
+
};
|
|
@@ -8,6 +8,11 @@ export declare const aiModelSchema: z.ZodEnum<{
|
|
|
8
8
|
}>;
|
|
9
9
|
export type AiModel = z.infer<typeof aiModelSchema>;
|
|
10
10
|
export declare const DEFAULT_AI_MODEL = "claude-opus-5";
|
|
11
|
+
export declare const aiInputDeclSchema: z.ZodObject<{
|
|
12
|
+
schema: z.ZodRecord<z.ZodString, z.ZodUnknown>;
|
|
13
|
+
resume: z.ZodOptional<z.ZodBoolean>;
|
|
14
|
+
}, z.core.$strip>;
|
|
15
|
+
export type AiInputDecl = z.infer<typeof aiInputDeclSchema>;
|
|
11
16
|
export declare const aiManifestSchema: z.ZodObject<{
|
|
12
17
|
name: z.ZodOptional<z.ZodString>;
|
|
13
18
|
description: z.ZodOptional<z.ZodString>;
|
|
@@ -21,7 +26,13 @@ export declare const aiManifestSchema: z.ZodObject<{
|
|
|
21
26
|
skills: z.ZodDefault<z.ZodArray<z.ZodString>>;
|
|
22
27
|
env: z.ZodDefault<z.ZodArray<z.ZodString>>;
|
|
23
28
|
verbose: z.ZodOptional<z.ZodBoolean>;
|
|
24
|
-
inputs: z.ZodRecord<z.ZodString, z.
|
|
29
|
+
inputs: z.ZodRecord<z.ZodString, z.ZodUnion<readonly [z.ZodObject<{
|
|
30
|
+
schema: z.ZodRecord<z.ZodString, z.ZodUnknown>;
|
|
31
|
+
resume: z.ZodOptional<z.ZodBoolean>;
|
|
32
|
+
}, z.core.$strip>, z.ZodPipe<z.ZodRecord<z.ZodString, z.ZodUnknown>, z.ZodTransform<{
|
|
33
|
+
schema: Record<string, unknown>;
|
|
34
|
+
resume?: boolean | undefined;
|
|
35
|
+
}, Record<string, unknown>>>]>>;
|
|
25
36
|
outputs: z.ZodRecord<z.ZodString, z.ZodRecord<z.ZodString, z.ZodUnknown>>;
|
|
26
37
|
}, z.core.$strip>;
|
|
27
38
|
export type AiManifest = z.infer<typeof aiManifestSchema>;
|
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
import { z } from "zod";
|
|
2
|
-
import { jsonSchemaSchema } from "./node.js";
|
|
3
|
-
import { isAiEnvelopeSchema, manifestInKeysViolation } from "./port-spec.js";
|
|
2
|
+
import { jsonSchemaSchema, PORT_KEY_PATTERN } from "./node.js";
|
|
4
3
|
// AI ノードのモデル選択肢(既定は Opus:下書き品質が価値の中心。費用はユーザー持ち)。
|
|
5
4
|
// エイリアス("opus" 等)は採らずバージョンを固定する:実行のたびに黙って別モデルへ
|
|
6
5
|
// 乗り換わると品質も費用も再現しないため。新モデルが出たらこの配列を足して SDK を publish する
|
|
@@ -12,6 +11,20 @@ export const AI_MODELS = [
|
|
|
12
11
|
];
|
|
13
12
|
export const aiModelSchema = z.enum(AI_MODELS);
|
|
14
13
|
export const DEFAULT_AI_MODEL = "claude-opus-5";
|
|
14
|
+
// 入力口の宣言:スキーマ+実行属性。resume: true の口から入力が届いた実行は
|
|
15
|
+
// 同じノードの直近セッションを復元して再開する(backend が ports.resume へ同期して
|
|
16
|
+
// payload 発行時に参照する。ポート型固定の撤去とセッション再開のポート属性化.md)
|
|
17
|
+
export const aiInputDeclSchema = z.object({
|
|
18
|
+
schema: jsonSchemaSchema,
|
|
19
|
+
resume: z.boolean().optional(),
|
|
20
|
+
});
|
|
21
|
+
// 旧形式(値が素の JSON Schema)は { schema: 値 } として読む。判別は「schema キーを
|
|
22
|
+
// 持つか」:JSON Schema のトップレベルに "schema" キーは現れない(メタスキーマ参照は
|
|
23
|
+
// "$schema")ので実用上一意。書き戻し(backend の syncNodeConfigs)は常に新形式で書く
|
|
24
|
+
const aiInputValueSchema = z.union([
|
|
25
|
+
aiInputDeclSchema,
|
|
26
|
+
jsonSchemaSchema.transform((schema) => ({ schema })),
|
|
27
|
+
]);
|
|
15
28
|
// nodes/ai/<dir>/config.json(実行repoの構造見直し)。AI ノードの定義(prompt/model/skills/
|
|
16
29
|
// 入出力スキーマ/env)は repo 側が正で、エディタが取り込んで ports を自動生成する
|
|
17
30
|
// (実行時の正は ports テーブルのまま。プログラム規約 v2 と同じ関係)。
|
|
@@ -34,34 +47,36 @@ export const aiManifestSchema = z
|
|
|
34
47
|
// 実行中の経過(発話・ツール呼び出し)を Actions ログへ逐次出すデバッグフラグ。
|
|
35
48
|
// 通常時は config.json にキーを書かない(インスペクタも false ならキーを消す)
|
|
36
49
|
verbose: z.boolean().optional(),
|
|
37
|
-
inputs: z.record(z.string(),
|
|
50
|
+
inputs: z.record(z.string(), aiInputValueSchema),
|
|
38
51
|
outputs: z.record(z.string(), jsonSchemaSchema),
|
|
39
52
|
})
|
|
40
53
|
.superRefine((manifest, ctx) => {
|
|
41
|
-
//
|
|
42
|
-
//
|
|
43
|
-
const
|
|
44
|
-
if (
|
|
45
|
-
ctx.addIssue({ code: "custom", path: ["inputs"], message: inViolation });
|
|
46
|
-
}
|
|
47
|
-
// outputs は1件以上・key 自由(複数出口=分岐。AIノードの複数出口(分岐).md)
|
|
48
|
-
if (Object.keys(manifest.outputs).length < 1) {
|
|
54
|
+
// inputs は1件以上・key 自由(in / instruction の固定構成は廃止。
|
|
55
|
+
// セッション再開は key ではなく resume 属性で決まる)
|
|
56
|
+
const inKeys = Object.keys(manifest.inputs);
|
|
57
|
+
if (inKeys.length < 1) {
|
|
49
58
|
ctx.addIssue({
|
|
50
59
|
code: "custom",
|
|
51
|
-
path: ["
|
|
52
|
-
message: "
|
|
60
|
+
path: ["inputs"],
|
|
61
|
+
message: "inputs は1件以上宣言してください",
|
|
53
62
|
});
|
|
54
63
|
}
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
// data=T は任意の JSON Schema)
|
|
58
|
-
for (const [key, schema] of Object.entries(manifest.outputs)) {
|
|
59
|
-
if (!isAiEnvelopeSchema(schema)) {
|
|
64
|
+
for (const key of inKeys) {
|
|
65
|
+
if (!PORT_KEY_PATTERN.test(key)) {
|
|
60
66
|
ctx.addIssue({
|
|
61
67
|
code: "custom",
|
|
62
|
-
path: ["
|
|
63
|
-
message: `
|
|
68
|
+
path: ["inputs", key],
|
|
69
|
+
message: `inputs の key が不正です: ${key}(英小文字始まり・英数字と _ のみ)`,
|
|
64
70
|
});
|
|
65
71
|
}
|
|
66
72
|
}
|
|
73
|
+
// outputs は1件以上・key 自由(複数出口=分岐。AIノードの複数出口(分岐).md)。
|
|
74
|
+
// スキーマは任意の JSON Schema(形の強制はしない)
|
|
75
|
+
if (Object.keys(manifest.outputs).length < 1) {
|
|
76
|
+
ctx.addIssue({
|
|
77
|
+
code: "custom",
|
|
78
|
+
path: ["outputs"],
|
|
79
|
+
message: "outputs は1件以上宣言してください",
|
|
80
|
+
});
|
|
81
|
+
}
|
|
67
82
|
});
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import type { GraphConnection, GraphNode } from "./graph.js";
|
|
2
|
+
export declare const duplicateSelection: (params: {
|
|
3
|
+
nodes: GraphNode[];
|
|
4
|
+
connections: GraphConnection[];
|
|
5
|
+
selectedIds: readonly string[];
|
|
6
|
+
dx: number;
|
|
7
|
+
dy: number;
|
|
8
|
+
newId: () => string;
|
|
9
|
+
}) => {
|
|
10
|
+
nodes: GraphNode[];
|
|
11
|
+
connections: GraphConnection[];
|
|
12
|
+
};
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
// 選択ノードのコピー&ペースト・複製(ノードのコピー&ペーストと複数選択.md)。
|
|
2
|
+
// 純関数(id 採番は newId で注入)。エディタとテストの両方から使う。
|
|
3
|
+
//
|
|
4
|
+
// グラフは全量置換 PUT なので、複製は「id を全部採番し直して足す」だけで成立する。
|
|
5
|
+
// ポート数の制約(in は kind ごとに固定・out は1以上)や (io,key) のノード内一意は
|
|
6
|
+
// ノードを丸ごと写すので自動的に保たれる。
|
|
7
|
+
export const duplicateSelection = (params) => {
|
|
8
|
+
const { nodes, connections, selectedIds, dx, dy, newId } = params;
|
|
9
|
+
const selected = new Set(selectedIds);
|
|
10
|
+
// start / end は回路の構造ノードなので複製しない(選択に混ざっていても落とす)。
|
|
11
|
+
// 並び順は元グラフのまま(選択の指定順に依存させない)
|
|
12
|
+
const portIdMap = new Map();
|
|
13
|
+
const copied = nodes
|
|
14
|
+
.filter((n) => selected.has(n.id) && n.kind !== "start" && n.kind !== "end")
|
|
15
|
+
.map((n) => ({
|
|
16
|
+
...n,
|
|
17
|
+
id: newId(),
|
|
18
|
+
ports: n.ports.map((p) => {
|
|
19
|
+
const portId = newId();
|
|
20
|
+
portIdMap.set(p.id, portId);
|
|
21
|
+
return { ...p, id: portId };
|
|
22
|
+
}),
|
|
23
|
+
position_x: n.position_x + dx,
|
|
24
|
+
position_y: n.position_y + dy,
|
|
25
|
+
}));
|
|
26
|
+
// 両端が複製対象のポートである線(=選択内で完結する線)だけを張り替えて写す。
|
|
27
|
+
// 外部との線(入口・出口)はコピーしない
|
|
28
|
+
const copiedConnections = connections.flatMap((c) => {
|
|
29
|
+
const from = portIdMap.get(c.from_port_id);
|
|
30
|
+
const to = portIdMap.get(c.to_port_id);
|
|
31
|
+
return from && to ? [{ from_port_id: from, to_port_id: to }] : [];
|
|
32
|
+
});
|
|
33
|
+
return { nodes: copied, connections: copiedConnections };
|
|
34
|
+
};
|
|
@@ -1,7 +1,9 @@
|
|
|
1
1
|
export const analyzeExtractSelection = (nodes, connections, selectedIds) => {
|
|
2
2
|
const selected = new Set(selectedIds);
|
|
3
|
-
|
|
4
|
-
|
|
3
|
+
// 1ノードからコンポーネント化できる(グループ化の「2つ以上」はエディタ側の
|
|
4
|
+
// 有効条件。コンポーネントの設定値(refs)と1ノードのコンポーネント化.md)
|
|
5
|
+
if (selected.size < 1) {
|
|
6
|
+
return { ok: false, reason: "ノードを選択してください" };
|
|
5
7
|
}
|
|
6
8
|
const selectedNodes = nodes.filter((n) => selected.has(n.id));
|
|
7
9
|
const flow = selectedNodes.find((n) => n.kind === "start" || n.kind === "end");
|
package/dist/_schemas/graph.d.ts
CHANGED
|
@@ -17,12 +17,12 @@ export declare const editableNodeKindSchema: z.ZodEnum<{
|
|
|
17
17
|
}>;
|
|
18
18
|
export type EditableNodeKind = z.infer<typeof editableNodeKindSchema>;
|
|
19
19
|
export declare const graphNodeKindSchema: z.ZodEnum<{
|
|
20
|
+
start: "start";
|
|
21
|
+
end: "end";
|
|
20
22
|
ai: "ai";
|
|
21
23
|
human: "human";
|
|
22
24
|
program: "program";
|
|
23
25
|
wait: "wait";
|
|
24
|
-
start: "start";
|
|
25
|
-
end: "end";
|
|
26
26
|
component: "component";
|
|
27
27
|
}>;
|
|
28
28
|
export type GraphNodeKind = z.infer<typeof graphNodeKindSchema>;
|
|
@@ -52,15 +52,14 @@ export declare const assignMemberSchema: z.ZodUnion<readonly [z.ZodUUID, z.ZodLi
|
|
|
52
52
|
export type AssignMember = z.infer<typeof assignMemberSchema>;
|
|
53
53
|
export declare const humanConfigSchema: z.ZodObject<{
|
|
54
54
|
view: z.ZodOptional<z.ZodString>;
|
|
55
|
-
view_config: z.ZodOptional<z.ZodNullable<z.ZodUnknown>>;
|
|
56
55
|
assignment: z.ZodObject<{
|
|
57
56
|
strategy: z.ZodDefault<z.ZodEnum<{
|
|
58
57
|
fixed: "fixed";
|
|
59
58
|
round_robin: "round_robin";
|
|
60
59
|
}>>;
|
|
61
60
|
approval_mode: z.ZodDefault<z.ZodEnum<{
|
|
62
|
-
any: "any";
|
|
63
61
|
all: "all";
|
|
62
|
+
any: "any";
|
|
64
63
|
}>>;
|
|
65
64
|
units: z.ZodDefault<z.ZodArray<z.ZodArray<z.ZodUnion<readonly [z.ZodUUID, z.ZodLiteral<"run_starter">]>>>>;
|
|
66
65
|
}, z.core.$strip>;
|
|
@@ -68,6 +67,7 @@ export declare const humanConfigSchema: z.ZodObject<{
|
|
|
68
67
|
export type HumanConfig = z.infer<typeof humanConfigSchema>;
|
|
69
68
|
export declare const componentConfigSchema: z.ZodObject<{
|
|
70
69
|
component_loop_id: z.ZodUUID;
|
|
70
|
+
refs: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodUnknown>>;
|
|
71
71
|
}, z.core.$strip>;
|
|
72
72
|
export type ComponentConfig = z.infer<typeof componentConfigSchema>;
|
|
73
73
|
export declare const graphNodeHookSchema: z.ZodObject<{
|
|
@@ -81,12 +81,12 @@ export type GraphNodeHook = z.infer<typeof graphNodeHookSchema>;
|
|
|
81
81
|
export declare const graphNodeSchema: z.ZodObject<{
|
|
82
82
|
id: z.ZodUUID;
|
|
83
83
|
kind: z.ZodEnum<{
|
|
84
|
+
start: "start";
|
|
85
|
+
end: "end";
|
|
84
86
|
ai: "ai";
|
|
85
87
|
human: "human";
|
|
86
88
|
program: "program";
|
|
87
89
|
wait: "wait";
|
|
88
|
-
start: "start";
|
|
89
|
-
end: "end";
|
|
90
90
|
component: "component";
|
|
91
91
|
}>;
|
|
92
92
|
name: z.ZodString;
|
|
@@ -99,6 +99,7 @@ export declare const graphNodeSchema: z.ZodObject<{
|
|
|
99
99
|
key: z.ZodString;
|
|
100
100
|
name: z.ZodString;
|
|
101
101
|
schema: z.ZodRecord<z.ZodString, z.ZodUnknown>;
|
|
102
|
+
resume: z.ZodOptional<z.ZodBoolean>;
|
|
102
103
|
side: z.ZodOptional<z.ZodEnum<{
|
|
103
104
|
top: "top";
|
|
104
105
|
right: "right";
|
|
@@ -136,21 +137,21 @@ export declare const graphNodeSchema: z.ZodObject<{
|
|
|
136
137
|
}, z.core.$strip>>;
|
|
137
138
|
human: z.ZodOptional<z.ZodObject<{
|
|
138
139
|
view: z.ZodOptional<z.ZodString>;
|
|
139
|
-
view_config: z.ZodOptional<z.ZodNullable<z.ZodUnknown>>;
|
|
140
140
|
assignment: z.ZodObject<{
|
|
141
141
|
strategy: z.ZodDefault<z.ZodEnum<{
|
|
142
142
|
fixed: "fixed";
|
|
143
143
|
round_robin: "round_robin";
|
|
144
144
|
}>>;
|
|
145
145
|
approval_mode: z.ZodDefault<z.ZodEnum<{
|
|
146
|
-
any: "any";
|
|
147
146
|
all: "all";
|
|
147
|
+
any: "any";
|
|
148
148
|
}>>;
|
|
149
149
|
units: z.ZodDefault<z.ZodArray<z.ZodArray<z.ZodUnion<readonly [z.ZodUUID, z.ZodLiteral<"run_starter">]>>>>;
|
|
150
150
|
}, z.core.$strip>;
|
|
151
151
|
}, z.core.$strip>>;
|
|
152
152
|
component: z.ZodOptional<z.ZodObject<{
|
|
153
153
|
component_loop_id: z.ZodUUID;
|
|
154
|
+
refs: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodUnknown>>;
|
|
154
155
|
}, z.core.$strip>>;
|
|
155
156
|
}, z.core.$strip>;
|
|
156
157
|
export type GraphNode = z.infer<typeof graphNodeSchema>;
|
|
@@ -163,12 +164,12 @@ export declare const saveGraphBodySchema: z.ZodObject<{
|
|
|
163
164
|
nodes: z.ZodArray<z.ZodObject<{
|
|
164
165
|
id: z.ZodUUID;
|
|
165
166
|
kind: z.ZodEnum<{
|
|
167
|
+
start: "start";
|
|
168
|
+
end: "end";
|
|
166
169
|
ai: "ai";
|
|
167
170
|
human: "human";
|
|
168
171
|
program: "program";
|
|
169
172
|
wait: "wait";
|
|
170
|
-
start: "start";
|
|
171
|
-
end: "end";
|
|
172
173
|
component: "component";
|
|
173
174
|
}>;
|
|
174
175
|
name: z.ZodString;
|
|
@@ -181,6 +182,7 @@ export declare const saveGraphBodySchema: z.ZodObject<{
|
|
|
181
182
|
key: z.ZodString;
|
|
182
183
|
name: z.ZodString;
|
|
183
184
|
schema: z.ZodRecord<z.ZodString, z.ZodUnknown>;
|
|
185
|
+
resume: z.ZodOptional<z.ZodBoolean>;
|
|
184
186
|
side: z.ZodOptional<z.ZodEnum<{
|
|
185
187
|
top: "top";
|
|
186
188
|
right: "right";
|
|
@@ -218,21 +220,21 @@ export declare const saveGraphBodySchema: z.ZodObject<{
|
|
|
218
220
|
}, z.core.$strip>>;
|
|
219
221
|
human: z.ZodOptional<z.ZodObject<{
|
|
220
222
|
view: z.ZodOptional<z.ZodString>;
|
|
221
|
-
view_config: z.ZodOptional<z.ZodNullable<z.ZodUnknown>>;
|
|
222
223
|
assignment: z.ZodObject<{
|
|
223
224
|
strategy: z.ZodDefault<z.ZodEnum<{
|
|
224
225
|
fixed: "fixed";
|
|
225
226
|
round_robin: "round_robin";
|
|
226
227
|
}>>;
|
|
227
228
|
approval_mode: z.ZodDefault<z.ZodEnum<{
|
|
228
|
-
any: "any";
|
|
229
229
|
all: "all";
|
|
230
|
+
any: "any";
|
|
230
231
|
}>>;
|
|
231
232
|
units: z.ZodDefault<z.ZodArray<z.ZodArray<z.ZodUnion<readonly [z.ZodUUID, z.ZodLiteral<"run_starter">]>>>>;
|
|
232
233
|
}, z.core.$strip>;
|
|
233
234
|
}, z.core.$strip>>;
|
|
234
235
|
component: z.ZodOptional<z.ZodObject<{
|
|
235
236
|
component_loop_id: z.ZodUUID;
|
|
237
|
+
refs: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodUnknown>>;
|
|
236
238
|
}, z.core.$strip>>;
|
|
237
239
|
}, z.core.$strip>>;
|
|
238
240
|
connections: z.ZodArray<z.ZodObject<{
|
package/dist/_schemas/graph.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { z } from "zod";
|
|
2
2
|
import { graphPortSchema, jsonSchemaSchema, nodeKindSchema, portKeySchema, } from "./node.js";
|
|
3
|
-
import {
|
|
3
|
+
import { hasInboundConflict, isSchemaSubset, kindPortsViolation, resolvePortSchemas, UNDECLARED_SCHEMA, } from "./port-spec.js";
|
|
4
4
|
// refs=ループ変数の袋(key→任意の JSON 値。上流出力の参照(refs).md)。
|
|
5
5
|
// run 開始時に定義から複製され、全 step に全量差し込まれる。
|
|
6
6
|
// key はポート key と同じ規則(^[a-z][a-z0-9_]*$)。実行系ボディ
|
|
@@ -107,8 +107,6 @@ export const humanConfigSchema = z.object({
|
|
|
107
107
|
// どのキーが実在するか・そのテナントが選べるかは保存時に mawaru 側が検証する
|
|
108
108
|
// (カタログは非公開。@mawaru/common の approval-view.ts)。省略時は標準ビュー
|
|
109
109
|
view: z.string().min(1).optional(),
|
|
110
|
-
// ビューに渡すパラメータ(列・ラベル・閾値など)。形はビューごとに違うので任意の JSON
|
|
111
|
-
view_config: z.unknown().nullish(),
|
|
112
110
|
assignment: z
|
|
113
111
|
.object({
|
|
114
112
|
strategy: z.enum(["fixed", "round_robin"]).default("fixed"),
|
|
@@ -158,6 +156,10 @@ export const humanConfigSchema = z.object({
|
|
|
158
156
|
// (docs/tasks/wip/コンポーネント(ループの部品化と再利用).md)
|
|
159
157
|
export const componentConfigSchema = z.object({
|
|
160
158
|
component_loop_id: z.uuid(),
|
|
159
|
+
// 配置の設定値:子 loop の refs 定義(default/required)への上書き。
|
|
160
|
+
// 子 run 起動時の起動時指定として渡る(省略=上書きなし。検証は保存 API と
|
|
161
|
+
// 起動時の mergeRefs が行う。コンポーネントの設定値(refs)と1ノードのコンポーネント化.md)
|
|
162
|
+
refs: z.record(z.string(), z.unknown()).optional(),
|
|
161
163
|
});
|
|
162
164
|
// ノードにアタッチされた IOHook(node_hooks に対応。アタッチできるのは program ノードのみ)。
|
|
163
165
|
// on_input / on_output / on_signal はアタッチ時に repo の config.json(hookManifestSchema)から
|
|
@@ -258,17 +260,16 @@ export const saveGraphBodySchema = z
|
|
|
258
260
|
outCount++;
|
|
259
261
|
});
|
|
260
262
|
// end は「in は1つ以上」(複数ルートを別々の in で集約する)。
|
|
261
|
-
// ai
|
|
263
|
+
// ai も1つ以上(in は自由ポート:追加・削除・key 自由)。他 kind は1つ固定。
|
|
262
264
|
// key の妥当性は kindPortsViolation が別途見る
|
|
263
|
-
const
|
|
264
|
-
const inCountOk = node.kind === "end" ? inCount >= 1 : inCount === expectIn;
|
|
265
|
+
const inCountOk = node.kind === "end" || node.kind === "ai" ? inCount >= 1 : inCount === 1;
|
|
265
266
|
if (!inCountOk) {
|
|
266
267
|
ctx.addIssue({
|
|
267
268
|
code: "custom",
|
|
268
269
|
path: ["nodes", i, "ports"],
|
|
269
|
-
message: node.kind === "end"
|
|
270
|
+
message: node.kind === "end" || node.kind === "ai"
|
|
270
271
|
? "in ポートが1つ以上必要です"
|
|
271
|
-
:
|
|
272
|
+
: "in ポートはちょうど1つ必要です",
|
|
272
273
|
});
|
|
273
274
|
}
|
|
274
275
|
if (outCount < 1) {
|
|
@@ -307,7 +308,8 @@ export const saveGraphBodySchema = z
|
|
|
307
308
|
message: "component ノードには component_loop_id が必要です",
|
|
308
309
|
});
|
|
309
310
|
}
|
|
310
|
-
// kind 別のポート構成(program 以外は数・key・io 固定。ポートのkind別仕様.md
|
|
311
|
+
// kind 別のポート構成(program 以外は数・key・io 固定。ポートのkind別仕様.md)。
|
|
312
|
+
// ポートのスキーマ自体は kind によらず任意の JSON Schema(形の強制はしない)
|
|
311
313
|
const violation = kindPortsViolation(node.kind, node.ports);
|
|
312
314
|
if (violation) {
|
|
313
315
|
ctx.addIssue({
|
|
@@ -316,19 +318,6 @@ export const saveGraphBodySchema = z
|
|
|
316
318
|
message: violation,
|
|
317
319
|
});
|
|
318
320
|
}
|
|
319
|
-
// AI の出力宣言は封筒型 { data: T, description: string }(T は任意の JSON Schema)。
|
|
320
|
-
// 複数出口でも全出口に強制する(どの出口も human に接続できる不変条件)
|
|
321
|
-
if (node.kind === "ai") {
|
|
322
|
-
node.ports.forEach((port, j) => {
|
|
323
|
-
if (port.io === "out" && !isAiEnvelopeSchema(port.schema)) {
|
|
324
|
-
ctx.addIssue({
|
|
325
|
-
code: "custom",
|
|
326
|
-
path: ["nodes", i, "ports", j],
|
|
327
|
-
message: "AI の出力は封筒型 { data, description } で宣言してください",
|
|
328
|
-
});
|
|
329
|
-
}
|
|
330
|
-
});
|
|
331
|
-
}
|
|
332
321
|
});
|
|
333
322
|
// 接続:両端がグラフ内の port を指し、from=out / to=in。
|
|
334
323
|
// 同じ out ポートから複数の in への fan-out は許す(並行分岐)。
|
|
@@ -409,49 +398,21 @@ export const saveGraphBodySchema = z
|
|
|
409
398
|
message: "終了ノードからは接続できません",
|
|
410
399
|
});
|
|
411
400
|
}
|
|
412
|
-
//
|
|
413
|
-
//
|
|
414
|
-
//
|
|
415
|
-
|
|
416
|
-
|
|
417
|
-
|
|
418
|
-
|
|
419
|
-
|
|
420
|
-
path: ["connections", i, "to_port_id"],
|
|
421
|
-
message: "差し戻し(reject)の接続先は AI ノードの instruction ポートのみです",
|
|
422
|
-
});
|
|
423
|
-
}
|
|
424
|
-
// instruction ポートに繋げるのは human の reject だけ(データを流し込ませない)
|
|
425
|
-
if (toNode.kind === "ai" &&
|
|
426
|
-
to.key === AI_INSTRUCTION_PORT_KEY &&
|
|
427
|
-
!(fromNode.kind === "human" && from.key === "reject")) {
|
|
428
|
-
ctx.addIssue({
|
|
429
|
-
code: "custom",
|
|
430
|
-
path: ["connections", i, "to_port_id"],
|
|
431
|
-
message: "instruction ポートに接続できるのは human の差し戻し(reject)だけです",
|
|
432
|
-
});
|
|
433
|
-
}
|
|
401
|
+
// 差し戻し(reject)と instruction の組み合わせに kind の縛りも型固定も無い:
|
|
402
|
+
// reject の型はビューの宣言、instruction は ai の in の1つ(接続鏡映)でしかない
|
|
403
|
+
// → docs/tasks/wip/ポート型固定の撤去とセッション再開のポート属性化.md
|
|
404
|
+
// 型検証は kind によらず常に 伝播型(out) ⊆ 伝播型(in)。
|
|
405
|
+
// 未宣言は unknown=判断できないので通す(作りかけのグラフを保存できなくしない)。
|
|
406
|
+
// 接続鏡映する口(program / ai の in)とコピー宣言のビューは接続元の型を採用する
|
|
407
|
+
// ので自明に通り、実質の検証対象は宣言で固定された口
|
|
408
|
+
// (component の契約・宣言のあるビューの human.in)になる
|
|
434
409
|
const fromSchema = resolved.get(conn.from_port_id) ?? from.schema;
|
|
435
|
-
// human の in はどの型でも接続できる(上流が AI なら封筒 { data, description }、
|
|
436
|
-
// それ以外は input 全体を data として表示する。型制約は課さない)
|
|
437
|
-
// program の in への接続は 伝播型 ⊆ 宣言スキーマ。in は接続鏡映(sticky)なので
|
|
438
|
-
// 具体型の接続では自明に通り、接続元が未宣言 × 宣言維持のときだけ従来の意味を持つ
|
|
439
|
-
// (未宣言は unknown=判断できないので通す。作りかけのグラフを保存できなくしない)
|
|
440
410
|
const toSchema = resolved.get(conn.to_port_id) ?? to.schema;
|
|
441
|
-
if (
|
|
442
|
-
ctx.addIssue({
|
|
443
|
-
code: "custom",
|
|
444
|
-
path: ["connections", i, "to_port_id"],
|
|
445
|
-
message: "接続元の型が program の入力スキーマに適合しません(伝播型 ⊆ 宣言スキーマ)",
|
|
446
|
-
});
|
|
447
|
-
}
|
|
448
|
-
// component の in は子 loop の契約(焼き込み済み宣言)。program と同じ包含チェック
|
|
449
|
-
if (toNode.kind === "component" &&
|
|
450
|
-
!isSchemaSubset(fromSchema, toSchema)) {
|
|
411
|
+
if (!isSchemaSubset(fromSchema, toSchema)) {
|
|
451
412
|
ctx.addIssue({
|
|
452
413
|
code: "custom",
|
|
453
414
|
path: ["connections", i, "to_port_id"],
|
|
454
|
-
message:
|
|
415
|
+
message: `「${fromNode.name}」の出力が「${toNode.name}」の入力スキーマに適合しません`,
|
|
455
416
|
});
|
|
456
417
|
}
|
|
457
418
|
});
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { z } from "zod";
|
|
2
2
|
export declare const hookEventSchema: z.ZodEnum<{
|
|
3
|
-
output: "output";
|
|
4
3
|
input: "input";
|
|
4
|
+
output: "output";
|
|
5
5
|
signal: "signal";
|
|
6
6
|
}>;
|
|
7
7
|
export type HookEvent = z.infer<typeof hookEventSchema>;
|
|
@@ -9,8 +9,8 @@ export declare const hookManifestSchema: z.ZodObject<{
|
|
|
9
9
|
name: z.ZodOptional<z.ZodString>;
|
|
10
10
|
description: z.ZodOptional<z.ZodString>;
|
|
11
11
|
on: z.ZodArray<z.ZodEnum<{
|
|
12
|
-
output: "output";
|
|
13
12
|
input: "input";
|
|
13
|
+
output: "output";
|
|
14
14
|
signal: "signal";
|
|
15
15
|
}>>;
|
|
16
16
|
env: z.ZodDefault<z.ZodArray<z.ZodString>>;
|
package/dist/_schemas/node.d.ts
CHANGED
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
import { z } from "zod";
|
|
2
2
|
export declare const nodeKindSchema: z.ZodEnum<{
|
|
3
|
+
start: "start";
|
|
4
|
+
end: "end";
|
|
3
5
|
ai: "ai";
|
|
4
6
|
human: "human";
|
|
5
7
|
program: "program";
|
|
6
8
|
guardrail: "guardrail";
|
|
7
9
|
wait: "wait";
|
|
8
|
-
start: "start";
|
|
9
|
-
end: "end";
|
|
10
10
|
component: "component";
|
|
11
11
|
}>;
|
|
12
12
|
export type NodeKind = z.infer<typeof nodeKindSchema>;
|
|
@@ -37,6 +37,7 @@ export declare const graphPortSchema: z.ZodObject<{
|
|
|
37
37
|
key: z.ZodString;
|
|
38
38
|
name: z.ZodString;
|
|
39
39
|
schema: z.ZodRecord<z.ZodString, z.ZodUnknown>;
|
|
40
|
+
resume: z.ZodOptional<z.ZodBoolean>;
|
|
40
41
|
side: z.ZodOptional<z.ZodEnum<{
|
|
41
42
|
top: "top";
|
|
42
43
|
right: "right";
|
package/dist/_schemas/node.js
CHANGED
|
@@ -36,6 +36,10 @@ export const graphPortSchema = z
|
|
|
36
36
|
key: portKeySchema,
|
|
37
37
|
name: z.string().min(1),
|
|
38
38
|
schema: jsonSchemaSchema,
|
|
39
|
+
// in ポートの実行属性:true ならこの口から届いた実行は前回セッションを復元して
|
|
40
|
+
// 再開する(AI ノードで意味を持つ。key ではなくこの属性が再開を決める。
|
|
41
|
+
// ポート型固定の撤去とセッション再開のポート属性化.md)
|
|
42
|
+
resume: z.boolean().optional(),
|
|
39
43
|
side: portSideSchema.optional(),
|
|
40
44
|
offset: z.number().min(0).max(1).optional(),
|
|
41
45
|
})
|
|
@@ -6,7 +6,6 @@ export declare const FILE_SCHEMA_MARKER = "x-mawaru-type";
|
|
|
6
6
|
export declare const FILE_SCHEMA_TYPE = "file";
|
|
7
7
|
export declare const fileSchema: () => JsonSchema;
|
|
8
8
|
export declare const isFileSchema: (schema: JsonSchema) => boolean;
|
|
9
|
-
export declare const AI_INSTRUCTION_PORT_KEY = "instruction";
|
|
10
9
|
export declare const instructionSchema: () => JsonSchema;
|
|
11
10
|
export declare const LIST_COLUMN_TYPES: readonly ["string", "number", "boolean", "date"];
|
|
12
11
|
export declare const listColumnTypeSchema: z.ZodEnum<{
|
|
@@ -45,9 +44,6 @@ export declare const dataFormatSchema: z.ZodDiscriminatedUnion<[z.ZodObject<{
|
|
|
45
44
|
export type DataFormat = z.infer<typeof dataFormatSchema>;
|
|
46
45
|
export declare const dataSchemaOf: (format: DataFormat) => JsonSchema;
|
|
47
46
|
export declare const dataFormatOf: (schema: JsonSchema) => DataFormat | null;
|
|
48
|
-
export declare const envelopeSchemaOf: (dataSchema: JsonSchema) => JsonSchema;
|
|
49
|
-
export declare const envelopeDataSchemaOf: (schema: JsonSchema) => JsonSchema | null;
|
|
50
|
-
export declare const isAiEnvelopeSchema: (schema: JsonSchema) => boolean;
|
|
51
47
|
export declare const fixedInKeysOf: (kind: string) => string[] | null;
|
|
52
48
|
export declare const manifestInKeysViolation: (kind: string, keys: string[]) => string | null;
|
|
53
49
|
export declare const kindPortsViolation: (kind: string, ports: Pick<GraphPort, "io" | "key">[]) => string | null;
|
|
@@ -62,8 +58,17 @@ type PortLink = {
|
|
|
62
58
|
from_port_id: string;
|
|
63
59
|
to_port_id: string;
|
|
64
60
|
};
|
|
65
|
-
export declare const
|
|
66
|
-
export
|
|
61
|
+
export declare const COPY_UPSTREAM_SCHEMA = "T";
|
|
62
|
+
export type DeclaredPortSchema = JsonSchema | typeof COPY_UPSTREAM_SCHEMA;
|
|
63
|
+
export type PropagationOptions<N> = {
|
|
64
|
+
viewPortSchemasOf?: (node: N) => {
|
|
65
|
+
in: DeclaredPortSchema;
|
|
66
|
+
approve: DeclaredPortSchema;
|
|
67
|
+
reject: JsonSchema;
|
|
68
|
+
} | null | undefined;
|
|
69
|
+
};
|
|
70
|
+
export declare const resolvePortSchemas: <N extends PropagationNode>(nodes: N[], connections: PortLink[], options?: PropagationOptions<N>) => Map<string, JsonSchema>;
|
|
71
|
+
export declare const propagateDerivedPorts: <N extends PropagationNode>(nodes: N[], connections: PortLink[], options?: PropagationOptions<N>) => N[];
|
|
67
72
|
export type SchemaFit = "ok" | "mismatch" | "unknown";
|
|
68
73
|
export declare const schemaFit: (sub: JsonSchema, sup: JsonSchema) => SchemaFit;
|
|
69
74
|
export declare const isSchemaSubset: (sub: JsonSchema, sup: JsonSchema) => boolean;
|