@lingjingai/scriptctl 0.49.6 → 0.49.8
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/changes/0.49.7.md +14 -0
- package/changes/0.49.8.md +13 -0
- package/dist/cli.js +39 -28
- package/dist/cli.js.map +1 -1
- package/dist/common.js +2 -4
- package/dist/common.js.map +1 -1
- package/dist/domain/script/patch/helpers.d.ts +8 -1
- package/dist/domain/script/patch/helpers.js +79 -7
- package/dist/domain/script/patch/helpers.js.map +1 -1
- package/dist/domain/script/patch/ops-asset.js +34 -10
- package/dist/domain/script/patch/ops-asset.js.map +1 -1
- package/dist/domain/script/patch/ops-scene.js +6 -1
- package/dist/domain/script/patch/ops-scene.js.map +1 -1
- package/dist/domain/script/patch/ops-state.js +28 -6
- package/dist/domain/script/patch/ops-state.js.map +1 -1
- package/dist/domain/script/schema.js +3 -3
- package/dist/domain/script/schema.js.map +1 -1
- package/dist/help-text.js +58 -31
- package/dist/help-text.js.map +1 -1
- package/dist/infra/script-output-api.d.ts +9 -6
- package/dist/infra/script-output-api.js +16 -3
- package/dist/infra/script-output-api.js.map +1 -1
- package/dist/infra/script-output-store.d.ts +16 -0
- package/dist/infra/script-output-store.js.map +1 -1
- package/dist/infra/script-working-copy.d.ts +22 -0
- package/dist/infra/script-working-copy.js +155 -0
- package/dist/infra/script-working-copy.js.map +1 -0
- package/dist/usecases/ingest/publish-command.d.ts +1 -4
- package/dist/usecases/ingest/publish-command.js +3 -76
- package/dist/usecases/ingest/publish-command.js.map +1 -1
- package/dist/usecases/script/context.js +7 -1
- package/dist/usecases/script/context.js.map +1 -1
- package/dist/usecases/script/create.js +12 -48
- package/dist/usecases/script/create.js.map +1 -1
- package/dist/usecases/script/lib.d.ts +2 -0
- package/dist/usecases/script/lib.js +35 -5
- package/dist/usecases/script/lib.js.map +1 -1
- package/dist/usecases/script/session.d.ts +2 -1
- package/dist/usecases/script/session.js +18 -49
- package/dist/usecases/script/session.js.map +1 -1
- package/dist/usecases/script/working-copy.d.ts +5 -0
- package/dist/usecases/script/working-copy.js +256 -0
- package/dist/usecases/script/working-copy.js.map +1 -0
- package/package.json +3 -1
- package/scripts/install-skill.mjs +3 -3
- package/skills/scriptctl/SKILL.md +28 -30
- package/skills/scriptctl/references/atomic-write-workflow.md +20 -10
- package/skills/scriptctl/references/ingest-workflow.md +8 -9
- package/skills/scriptctl/references/production-writing-standard.md +8 -8
|
@@ -125,8 +125,8 @@ async function gatewayRequest(gatewayBase, accessKey, timeoutMs, method, path, o
|
|
|
125
125
|
}
|
|
126
126
|
/**
|
|
127
127
|
* V2 script-output store. Same gateway base + X-Access-Key auth as V1, but:
|
|
128
|
-
* -
|
|
129
|
-
*
|
|
128
|
+
* - publishScript is the strict-CAS whole-document write used by current clients.
|
|
129
|
+
* - replaceScript remains only as the legacy requestId-shaped client surface.
|
|
130
130
|
* - patchScript sends an RFC6902 PATCH (the compare() diff of old→edited),
|
|
131
131
|
* which V1 cannot do (it degrades to a whole-document replace).
|
|
132
132
|
*
|
|
@@ -134,7 +134,8 @@ async function gatewayRequest(gatewayBase, accessKey, timeoutMs, method, path, o
|
|
|
134
134
|
* remoteScriptOutputStoreFromEnv). Endpoints:
|
|
135
135
|
* GET {prefix}/{projectGroupNo}
|
|
136
136
|
* GET {prefix}/{projectGroupNo}/revision
|
|
137
|
-
*
|
|
137
|
+
* GET {prefix}/{projectGroupNo}/snapshot
|
|
138
|
+
* PUT {prefix}/{projectGroupNo} { baseRevision, script, validation }
|
|
138
139
|
* PATCH {prefix}/{projectGroupNo} RFC6902 patch array (wrapped with requestId)
|
|
139
140
|
* DELETE {prefix}/{projectGroupNo}
|
|
140
141
|
*/
|
|
@@ -173,6 +174,18 @@ export class ScriptV2OutputStore {
|
|
|
173
174
|
async getRevision() {
|
|
174
175
|
return (await this.request("GET", `${this.projectPrefix}/revision`, { allowMissing: true }));
|
|
175
176
|
}
|
|
177
|
+
async getSnapshot() {
|
|
178
|
+
return (await this.request("GET", `${this.projectPrefix}/snapshot`, { allowMissing: true }));
|
|
179
|
+
}
|
|
180
|
+
async publishScript(opts) {
|
|
181
|
+
return (await this.request("PUT", this.projectPrefix, {
|
|
182
|
+
body: {
|
|
183
|
+
baseRevision: opts.baseRevision,
|
|
184
|
+
script: opts.script,
|
|
185
|
+
validation: opts.validation,
|
|
186
|
+
},
|
|
187
|
+
}));
|
|
188
|
+
}
|
|
176
189
|
async replaceScript(opts) {
|
|
177
190
|
// V2 takes the whole script in one PUT — assert the same body-size limit as
|
|
178
191
|
// V1's begin body so an oversized document fails fast with the same error.
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"script-output-api.js","sourceRoot":"","sources":["../../src/infra/script-output-api.ts"],"names":[],"mappings":"AAAA,+EAA+E;AAC/E,+EAA+E;AAC/E,8EAA8E;AAC9E,OAAO,aAAa,MAAM,iBAAiB,CAAC;AAC5C,MAAM,EAAE,OAAO,EAAE,GAAG,aAAa,CAAC;AAElC,OAAO,EACL,oBAAoB,
|
|
1
|
+
{"version":3,"file":"script-output-api.js","sourceRoot":"","sources":["../../src/infra/script-output-api.ts"],"names":[],"mappings":"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"}
|
|
@@ -24,6 +24,22 @@ export interface ReplaceScriptOptions {
|
|
|
24
24
|
script: Record<string, unknown>;
|
|
25
25
|
source?: string;
|
|
26
26
|
}
|
|
27
|
+
export interface ScriptSnapshot {
|
|
28
|
+
projectGroupNo: string;
|
|
29
|
+
script: Record<string, unknown>;
|
|
30
|
+
revision: number;
|
|
31
|
+
validationStatus?: string | null;
|
|
32
|
+
validationSummary?: Record<string, unknown> | null;
|
|
33
|
+
updatedAt?: string | null;
|
|
34
|
+
}
|
|
35
|
+
export interface PublishScriptOptions {
|
|
36
|
+
baseRevision: number;
|
|
37
|
+
script: Record<string, unknown>;
|
|
38
|
+
validation: {
|
|
39
|
+
status: "valid";
|
|
40
|
+
summary: Record<string, unknown>;
|
|
41
|
+
};
|
|
42
|
+
}
|
|
27
43
|
/**
|
|
28
44
|
* Incremental edit: publish the RFC6902 diff between the loaded script and the
|
|
29
45
|
* locally-edited script, instead of re-uploading the whole document. `old` is
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"script-output-store.js","sourceRoot":"","sources":["../../src/infra/script-output-store.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,UAAU,EAAE,UAAU,EAAE,MAAM,cAAc,CAAC;AAiBhE,MAAM,OAAO,oBAAqB,SAAQ,KAAK;IACpC,MAAM,CAAgB;IACtB,IAAI,CAAyB;IAC7B,OAAO,CAAU;IACjB,aAAa,CAA2B;IAEjD,YAAY,OAAe,EAAE,OAAoC,EAAE;QACjE,KAAK,CAAC,OAAO,CAAC,CAAC;QACf,IAAI,CAAC,IAAI,GAAG,sBAAsB,CAAC;QACnC,IAAI,CAAC,MAAM,GAAG,IAAI,CAAC,MAAM,IAAI,IAAI,CAAC;QAClC,IAAI,CAAC,IAAI,GAAG,IAAI,CAAC,IAAI,IAAI,IAAI,CAAC;QAC9B,IAAI,CAAC,OAAO,GAAG,IAAI,CAAC,OAAO,CAAC;QAC5B,IAAI,CAAC,aAAa,GAAG,IAAI,CAAC,aAAa,IAAI,IAAI,CAAC;IAClD,CAAC;CACF;
|
|
1
|
+
{"version":3,"file":"script-output-store.js","sourceRoot":"","sources":["../../src/infra/script-output-store.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
export interface WorkingCopyMetadata {
|
|
2
|
+
schemaVersion: 1;
|
|
3
|
+
projectGroupNo: string;
|
|
4
|
+
apiBaseUrl: string;
|
|
5
|
+
baseRevision: number;
|
|
6
|
+
baseContentHash: string;
|
|
7
|
+
}
|
|
8
|
+
export interface WorkingCopyPaths {
|
|
9
|
+
scriptPath: string;
|
|
10
|
+
stateDir: string;
|
|
11
|
+
metadataPath: string;
|
|
12
|
+
lockPath: string;
|
|
13
|
+
}
|
|
14
|
+
export declare function semanticScriptHash(script: unknown): string;
|
|
15
|
+
export declare function localFileFingerprint(filePath: string): string | null;
|
|
16
|
+
export declare function assertLocalFileFingerprint(filePath: string, expected: string | null): void;
|
|
17
|
+
export declare function workingCopyPaths(rawScriptPath: string): WorkingCopyPaths;
|
|
18
|
+
export declare function withScriptFileLock<T>(rawScriptPath: string, operation: () => Promise<T>): Promise<T>;
|
|
19
|
+
export declare function atomicWriteJson(filePath: string, value: unknown): void;
|
|
20
|
+
export declare function readWorkingCopyMetadata(rawScriptPath: string): WorkingCopyMetadata | null;
|
|
21
|
+
export declare function writeWorkingCopyMetadata(rawScriptPath: string, metadata: WorkingCopyMetadata): void;
|
|
22
|
+
export declare function assertScriptUnchanged(scriptPath: string, expectedHash: string): void;
|
|
@@ -0,0 +1,155 @@
|
|
|
1
|
+
import * as crypto from "node:crypto";
|
|
2
|
+
import * as fs from "node:fs";
|
|
3
|
+
import * as path from "node:path";
|
|
4
|
+
import lockfile from "proper-lockfile";
|
|
5
|
+
import { CliError, EXIT_INPUT, EXIT_RUNTIME } from "../common.js";
|
|
6
|
+
function canonicalize(value) {
|
|
7
|
+
if (Array.isArray(value))
|
|
8
|
+
return value.map(canonicalize);
|
|
9
|
+
if (value !== null && typeof value === "object") {
|
|
10
|
+
const source = value;
|
|
11
|
+
const result = {};
|
|
12
|
+
for (const key of Object.keys(source).sort())
|
|
13
|
+
result[key] = canonicalize(source[key]);
|
|
14
|
+
return result;
|
|
15
|
+
}
|
|
16
|
+
return value;
|
|
17
|
+
}
|
|
18
|
+
export function semanticScriptHash(script) {
|
|
19
|
+
const canonical = JSON.stringify(canonicalize(script));
|
|
20
|
+
return `sha256:${crypto.createHash("sha256").update(canonical).digest("hex")}`;
|
|
21
|
+
}
|
|
22
|
+
export function localFileFingerprint(filePath) {
|
|
23
|
+
if (!fs.existsSync(filePath))
|
|
24
|
+
return null;
|
|
25
|
+
return `sha256:${crypto.createHash("sha256").update(fs.readFileSync(filePath)).digest("hex")}`;
|
|
26
|
+
}
|
|
27
|
+
export function assertLocalFileFingerprint(filePath, expected) {
|
|
28
|
+
const current = localFileFingerprint(filePath);
|
|
29
|
+
if (current === expected)
|
|
30
|
+
return;
|
|
31
|
+
throw new CliError("SCRIPT BLOCKED: local script changed", "The local script changed while the command was running.", {
|
|
32
|
+
exitCode: EXIT_INPUT,
|
|
33
|
+
errorCode: "LOCAL_SCRIPT_CHANGED",
|
|
34
|
+
received: [`loadedFingerprint=${expected ?? "<missing>"}`, `currentFingerprint=${current ?? "<missing>"}`, filePath],
|
|
35
|
+
nextSteps: ["Read the latest local script and retry the command."],
|
|
36
|
+
});
|
|
37
|
+
}
|
|
38
|
+
export function workingCopyPaths(rawScriptPath) {
|
|
39
|
+
const scriptPath = path.resolve(rawScriptPath);
|
|
40
|
+
const stateDir = path.join(path.dirname(scriptPath), ".scriptctl");
|
|
41
|
+
const name = path.basename(scriptPath);
|
|
42
|
+
return {
|
|
43
|
+
scriptPath,
|
|
44
|
+
stateDir,
|
|
45
|
+
metadataPath: path.join(stateDir, `${name}.working-copy.json`),
|
|
46
|
+
lockPath: path.join(stateDir, name),
|
|
47
|
+
};
|
|
48
|
+
}
|
|
49
|
+
export async function withScriptFileLock(rawScriptPath, operation) {
|
|
50
|
+
const paths = workingCopyPaths(rawScriptPath);
|
|
51
|
+
fs.mkdirSync(paths.stateDir, { recursive: true });
|
|
52
|
+
let release = null;
|
|
53
|
+
try {
|
|
54
|
+
release = await lockfile.lock(paths.lockPath, {
|
|
55
|
+
realpath: false,
|
|
56
|
+
stale: 120_000,
|
|
57
|
+
update: 10_000,
|
|
58
|
+
retries: { retries: 60, factor: 1, minTimeout: 500, maxTimeout: 500 },
|
|
59
|
+
});
|
|
60
|
+
}
|
|
61
|
+
catch (error) {
|
|
62
|
+
throw new CliError("SCRIPT BLOCKED: working copy is busy", "Timed out waiting for the script file lock.", {
|
|
63
|
+
exitCode: EXIT_RUNTIME,
|
|
64
|
+
errorCode: "WORKING_COPY_LOCK_TIMEOUT",
|
|
65
|
+
received: [paths.scriptPath, error instanceof Error ? error.message : String(error)],
|
|
66
|
+
nextSteps: ["Wait for the other scriptctl command to finish, then retry."],
|
|
67
|
+
});
|
|
68
|
+
}
|
|
69
|
+
try {
|
|
70
|
+
return await operation();
|
|
71
|
+
}
|
|
72
|
+
finally {
|
|
73
|
+
await release();
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
export function atomicWriteJson(filePath, value) {
|
|
77
|
+
const dir = path.dirname(filePath);
|
|
78
|
+
fs.mkdirSync(dir, { recursive: true });
|
|
79
|
+
const tempPath = path.join(dir, `.${path.basename(filePath)}.${process.pid}.${crypto.randomUUID()}.tmp`);
|
|
80
|
+
const descriptor = fs.openSync(tempPath, "wx");
|
|
81
|
+
try {
|
|
82
|
+
fs.writeFileSync(descriptor, `${JSON.stringify(value, null, 2)}\n`, "utf-8");
|
|
83
|
+
fs.fsyncSync(descriptor);
|
|
84
|
+
}
|
|
85
|
+
finally {
|
|
86
|
+
fs.closeSync(descriptor);
|
|
87
|
+
}
|
|
88
|
+
fs.renameSync(tempPath, filePath);
|
|
89
|
+
}
|
|
90
|
+
export function readWorkingCopyMetadata(rawScriptPath) {
|
|
91
|
+
const metadataPath = workingCopyPaths(rawScriptPath).metadataPath;
|
|
92
|
+
if (!fs.existsSync(metadataPath))
|
|
93
|
+
return null;
|
|
94
|
+
let value;
|
|
95
|
+
try {
|
|
96
|
+
value = JSON.parse(fs.readFileSync(metadataPath, "utf-8"));
|
|
97
|
+
}
|
|
98
|
+
catch (error) {
|
|
99
|
+
throw invalidMetadata(metadataPath, error instanceof Error ? error.message : String(error));
|
|
100
|
+
}
|
|
101
|
+
if (value === null || typeof value !== "object" || Array.isArray(value)) {
|
|
102
|
+
throw invalidMetadata(metadataPath, "metadata root must be an object");
|
|
103
|
+
}
|
|
104
|
+
const record = value;
|
|
105
|
+
if (record.schemaVersion !== 1
|
|
106
|
+
|| typeof record.projectGroupNo !== "string" || record.projectGroupNo.length === 0
|
|
107
|
+
|| typeof record.apiBaseUrl !== "string" || record.apiBaseUrl.length === 0
|
|
108
|
+
|| !Number.isInteger(record.baseRevision) || Number(record.baseRevision) < 0
|
|
109
|
+
|| typeof record.baseContentHash !== "string" || !record.baseContentHash.startsWith("sha256:")) {
|
|
110
|
+
throw invalidMetadata(metadataPath, "required fields are missing or invalid");
|
|
111
|
+
}
|
|
112
|
+
return {
|
|
113
|
+
schemaVersion: 1,
|
|
114
|
+
projectGroupNo: record.projectGroupNo,
|
|
115
|
+
apiBaseUrl: record.apiBaseUrl,
|
|
116
|
+
baseRevision: Number(record.baseRevision),
|
|
117
|
+
baseContentHash: record.baseContentHash,
|
|
118
|
+
};
|
|
119
|
+
}
|
|
120
|
+
export function writeWorkingCopyMetadata(rawScriptPath, metadata) {
|
|
121
|
+
atomicWriteJson(workingCopyPaths(rawScriptPath).metadataPath, metadata);
|
|
122
|
+
}
|
|
123
|
+
function invalidMetadata(metadataPath, reason) {
|
|
124
|
+
return new CliError("SCRIPT BLOCKED: working copy metadata invalid", "Working copy metadata is invalid.", {
|
|
125
|
+
exitCode: EXIT_INPUT,
|
|
126
|
+
errorCode: "WORKING_COPY_METADATA_INVALID",
|
|
127
|
+
required: ["valid scriptctl working-copy metadata"],
|
|
128
|
+
received: [metadataPath, reason],
|
|
129
|
+
nextSteps: ["Run `scriptctl checkout --discard-local` to recreate the working copy metadata."],
|
|
130
|
+
});
|
|
131
|
+
}
|
|
132
|
+
export function assertScriptUnchanged(scriptPath, expectedHash) {
|
|
133
|
+
let current;
|
|
134
|
+
try {
|
|
135
|
+
current = JSON.parse(fs.readFileSync(scriptPath, "utf-8"));
|
|
136
|
+
}
|
|
137
|
+
catch (error) {
|
|
138
|
+
throw new CliError("SCRIPT BLOCKED: local script changed", "The local script changed while the command was running.", {
|
|
139
|
+
exitCode: EXIT_INPUT,
|
|
140
|
+
errorCode: "LOCAL_SCRIPT_CHANGED",
|
|
141
|
+
received: [scriptPath, error instanceof Error ? error.message : String(error)],
|
|
142
|
+
nextSteps: ["Read the latest local script and re-apply the operation."],
|
|
143
|
+
});
|
|
144
|
+
}
|
|
145
|
+
const currentHash = semanticScriptHash(current);
|
|
146
|
+
if (currentHash !== expectedHash) {
|
|
147
|
+
throw new CliError("SCRIPT BLOCKED: local script changed", "The local script changed while the command was running.", {
|
|
148
|
+
exitCode: EXIT_INPUT,
|
|
149
|
+
errorCode: "LOCAL_SCRIPT_CHANGED",
|
|
150
|
+
received: [`loadedHash=${expectedHash}`, `currentHash=${currentHash}`, scriptPath],
|
|
151
|
+
nextSteps: ["Read the latest local script and re-apply the operation."],
|
|
152
|
+
});
|
|
153
|
+
}
|
|
154
|
+
}
|
|
155
|
+
//# sourceMappingURL=script-working-copy.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"script-working-copy.js","sourceRoot":"","sources":["../../src/infra/script-working-copy.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,MAAM,aAAa,CAAC;AACtC,OAAO,KAAK,EAAE,MAAM,SAAS,CAAC;AAC9B,OAAO,KAAK,IAAI,MAAM,WAAW,CAAC;AAElC,OAAO,QAAQ,MAAM,iBAAiB,CAAC;AAEvC,OAAO,EAAE,QAAQ,EAAE,UAAU,EAAE,YAAY,EAAE,MAAM,cAAc,CAAC;AAiBlE,SAAS,YAAY,CAAC,KAAc;IAClC,IAAI,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC;QAAE,OAAO,KAAK,CAAC,GAAG,CAAC,YAAY,CAAC,CAAC;IACzD,IAAI,KAAK,KAAK,IAAI,IAAI,OAAO,KAAK,KAAK,QAAQ,EAAE,CAAC;QAChD,MAAM,MAAM,GAAG,KAAgC,CAAC;QAChD,MAAM,MAAM,GAA4B,EAAE,CAAC;QAC3C,KAAK,MAAM,GAAG,IAAI,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC,IAAI,EAAE;YAAE,MAAM,CAAC,GAAG,CAAC,GAAG,YAAY,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC;QACtF,OAAO,MAAM,CAAC;IAChB,CAAC;IACD,OAAO,KAAK,CAAC;AACf,CAAC;AAED,MAAM,UAAU,kBAAkB,CAAC,MAAe;IAChD,MAAM,SAAS,GAAG,IAAI,CAAC,SAAS,CAAC,YAAY,CAAC,MAAM,CAAC,CAAC,CAAC;IACvD,OAAO,UAAU,MAAM,CAAC,UAAU,CAAC,QAAQ,CAAC,CAAC,MAAM,CAAC,SAAS,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,EAAE,CAAC;AACjF,CAAC;AAED,MAAM,UAAU,oBAAoB,CAAC,QAAgB;IACnD,IAAI,CAAC,EAAE,CAAC,UAAU,CAAC,QAAQ,CAAC;QAAE,OAAO,IAAI,CAAC;IAC1C,OAAO,UAAU,MAAM,CAAC,UAAU,CAAC,QAAQ,CAAC,CAAC,MAAM,CAAC,EAAE,CAAC,YAAY,CAAC,QAAQ,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,EAAE,CAAC;AACjG,CAAC;AAED,MAAM,UAAU,0BAA0B,CAAC,QAAgB,EAAE,QAAuB;IAClF,MAAM,OAAO,GAAG,oBAAoB,CAAC,QAAQ,CAAC,CAAC;IAC/C,IAAI,OAAO,KAAK,QAAQ;QAAE,OAAO;IACjC,MAAM,IAAI,QAAQ,CAAC,sCAAsC,EAAE,yDAAyD,EAAE;QACpH,QAAQ,EAAE,UAAU;QACpB,SAAS,EAAE,sBAAsB;QACjC,QAAQ,EAAE,CAAC,qBAAqB,QAAQ,IAAI,WAAW,EAAE,EAAE,sBAAsB,OAAO,IAAI,WAAW,EAAE,EAAE,QAAQ,CAAC;QACpH,SAAS,EAAE,CAAC,qDAAqD,CAAC;KACnE,CAAC,CAAC;AACL,CAAC;AAED,MAAM,UAAU,gBAAgB,CAAC,aAAqB;IACpD,MAAM,UAAU,GAAG,IAAI,CAAC,OAAO,CAAC,aAAa,CAAC,CAAC;IAC/C,MAAM,QAAQ,GAAG,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,OAAO,CAAC,UAAU,CAAC,EAAE,YAAY,CAAC,CAAC;IACnE,MAAM,IAAI,GAAG,IAAI,CAAC,QAAQ,CAAC,UAAU,CAAC,CAAC;IACvC,OAAO;QACL,UAAU;QACV,QAAQ;QACR,YAAY,EAAE,IAAI,CAAC,IAAI,CAAC,QAAQ,EAAE,GAAG,IAAI,oBAAoB,CAAC;QAC9D,QAAQ,EAAE,IAAI,CAAC,IAAI,CAAC,QAAQ,EAAE,IAAI,CAAC;KACpC,CAAC;AACJ,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,kBAAkB,CAAI,aAAqB,EAAE,SAA2B;IAC5F,MAAM,KAAK,GAAG,gBAAgB,CAAC,aAAa,CAAC,CAAC;IAC9C,EAAE,CAAC,SAAS,CAAC,KAAK,CAAC,QAAQ,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;IAClD,IAAI,OAAO,GAAiC,IAAI,CAAC;IACjD,IAAI,CAAC;QACH,OAAO,GAAG,MAAM,QAAQ,CAAC,IAAI,CAAC,KAAK,CAAC,QAAQ,EAAE;YAC5C,QAAQ,EAAE,KAAK;YACf,KAAK,EAAE,OAAO;YACd,MAAM,EAAE,MAAM;YACd,OAAO,EAAE,EAAE,OAAO,EAAE,EAAE,EAAE,MAAM,EAAE,CAAC,EAAE,UAAU,EAAE,GAAG,EAAE,UAAU,EAAE,GAAG,EAAE;SACtE,CAAC,CAAC;IACL,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,MAAM,IAAI,QAAQ,CAAC,sCAAsC,EAAE,6CAA6C,EAAE;YACxG,QAAQ,EAAE,YAAY;YACtB,SAAS,EAAE,2BAA2B;YACtC,QAAQ,EAAE,CAAC,KAAK,CAAC,UAAU,EAAE,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;YACpF,SAAS,EAAE,CAAC,6DAA6D,CAAC;SAC3E,CAAC,CAAC;IACL,CAAC;IACD,IAAI,CAAC;QACH,OAAO,MAAM,SAAS,EAAE,CAAC;IAC3B,CAAC;YAAS,CAAC;QACT,MAAM,OAAO,EAAE,CAAC;IAClB,CAAC;AACH,CAAC;AAED,MAAM,UAAU,eAAe,CAAC,QAAgB,EAAE,KAAc;IAC9D,MAAM,GAAG,GAAG,IAAI,CAAC,OAAO,CAAC,QAAQ,CAAC,CAAC;IACnC,EAAE,CAAC,SAAS,CAAC,GAAG,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;IACvC,MAAM,QAAQ,GAAG,IAAI,CAAC,IAAI,CAAC,GAAG,EAAE,IAAI,IAAI,CAAC,QAAQ,CAAC,QAAQ,CAAC,IAAI,OAAO,CAAC,GAAG,IAAI,MAAM,CAAC,UAAU,EAAE,MAAM,CAAC,CAAC;IACzG,MAAM,UAAU,GAAG,EAAE,CAAC,QAAQ,CAAC,QAAQ,EAAE,IAAI,CAAC,CAAC;IAC/C,IAAI,CAAC;QACH,EAAE,CAAC,aAAa,CAAC,UAAU,EAAE,GAAG,IAAI,CAAC,SAAS,CAAC,KAAK,EAAE,IAAI,EAAE,CAAC,CAAC,IAAI,EAAE,OAAO,CAAC,CAAC;QAC7E,EAAE,CAAC,SAAS,CAAC,UAAU,CAAC,CAAC;IAC3B,CAAC;YAAS,CAAC;QACT,EAAE,CAAC,SAAS,CAAC,UAAU,CAAC,CAAC;IAC3B,CAAC;IACD,EAAE,CAAC,UAAU,CAAC,QAAQ,EAAE,QAAQ,CAAC,CAAC;AACpC,CAAC;AAED,MAAM,UAAU,uBAAuB,CAAC,aAAqB;IAC3D,MAAM,YAAY,GAAG,gBAAgB,CAAC,aAAa,CAAC,CAAC,YAAY,CAAC;IAClE,IAAI,CAAC,EAAE,CAAC,UAAU,CAAC,YAAY,CAAC;QAAE,OAAO,IAAI,CAAC;IAC9C,IAAI,KAAc,CAAC;IACnB,IAAI,CAAC;QACH,KAAK,GAAG,IAAI,CAAC,KAAK,CAAC,EAAE,CAAC,YAAY,CAAC,YAAY,EAAE,OAAO,CAAC,CAAC,CAAC;IAC7D,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,MAAM,eAAe,CAAC,YAAY,EAAE,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC;IAC9F,CAAC;IACD,IAAI,KAAK,KAAK,IAAI,IAAI,OAAO,KAAK,KAAK,QAAQ,IAAI,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC,EAAE,CAAC;QACxE,MAAM,eAAe,CAAC,YAAY,EAAE,iCAAiC,CAAC,CAAC;IACzE,CAAC;IACD,MAAM,MAAM,GAAG,KAAgC,CAAC;IAChD,IAAI,MAAM,CAAC,aAAa,KAAK,CAAC;WACvB,OAAO,MAAM,CAAC,cAAc,KAAK,QAAQ,IAAI,MAAM,CAAC,cAAc,CAAC,MAAM,KAAK,CAAC;WAC/E,OAAO,MAAM,CAAC,UAAU,KAAK,QAAQ,IAAI,MAAM,CAAC,UAAU,CAAC,MAAM,KAAK,CAAC;WACvE,CAAC,MAAM,CAAC,SAAS,CAAC,MAAM,CAAC,YAAY,CAAC,IAAI,MAAM,CAAC,MAAM,CAAC,YAAY,CAAC,GAAG,CAAC;WACzE,OAAO,MAAM,CAAC,eAAe,KAAK,QAAQ,IAAI,CAAC,MAAM,CAAC,eAAe,CAAC,UAAU,CAAC,SAAS,CAAC,EAAE,CAAC;QACnG,MAAM,eAAe,CAAC,YAAY,EAAE,wCAAwC,CAAC,CAAC;IAChF,CAAC;IACD,OAAO;QACL,aAAa,EAAE,CAAC;QAChB,cAAc,EAAE,MAAM,CAAC,cAAc;QACrC,UAAU,EAAE,MAAM,CAAC,UAAU;QAC7B,YAAY,EAAE,MAAM,CAAC,MAAM,CAAC,YAAY,CAAC;QACzC,eAAe,EAAE,MAAM,CAAC,eAAe;KACxC,CAAC;AACJ,CAAC;AAED,MAAM,UAAU,wBAAwB,CAAC,aAAqB,EAAE,QAA6B;IAC3F,eAAe,CAAC,gBAAgB,CAAC,aAAa,CAAC,CAAC,YAAY,EAAE,QAAQ,CAAC,CAAC;AAC1E,CAAC;AAED,SAAS,eAAe,CAAC,YAAoB,EAAE,MAAc;IAC3D,OAAO,IAAI,QAAQ,CAAC,+CAA+C,EAAE,mCAAmC,EAAE;QACxG,QAAQ,EAAE,UAAU;QACpB,SAAS,EAAE,+BAA+B;QAC1C,QAAQ,EAAE,CAAC,uCAAuC,CAAC;QACnD,QAAQ,EAAE,CAAC,YAAY,EAAE,MAAM,CAAC;QAChC,SAAS,EAAE,CAAC,iFAAiF,CAAC;KAC/F,CAAC,CAAC;AACL,CAAC;AAED,MAAM,UAAU,qBAAqB,CAAC,UAAkB,EAAE,YAAoB;IAC5E,IAAI,OAAgB,CAAC;IACrB,IAAI,CAAC;QACH,OAAO,GAAG,IAAI,CAAC,KAAK,CAAC,EAAE,CAAC,YAAY,CAAC,UAAU,EAAE,OAAO,CAAC,CAAC,CAAC;IAC7D,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,MAAM,IAAI,QAAQ,CAAC,sCAAsC,EAAE,yDAAyD,EAAE;YACpH,QAAQ,EAAE,UAAU;YACpB,SAAS,EAAE,sBAAsB;YACjC,QAAQ,EAAE,CAAC,UAAU,EAAE,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;YAC9E,SAAS,EAAE,CAAC,0DAA0D,CAAC;SACxE,CAAC,CAAC;IACL,CAAC;IACD,MAAM,WAAW,GAAG,kBAAkB,CAAC,OAAO,CAAC,CAAC;IAChD,IAAI,WAAW,KAAK,YAAY,EAAE,CAAC;QACjC,MAAM,IAAI,QAAQ,CAAC,sCAAsC,EAAE,yDAAyD,EAAE;YACpH,QAAQ,EAAE,UAAU;YACpB,SAAS,EAAE,sBAAsB;YACjC,QAAQ,EAAE,CAAC,cAAc,YAAY,EAAE,EAAE,eAAe,WAAW,EAAE,EAAE,UAAU,CAAC;YAClF,SAAS,EAAE,CAAC,0DAA0D,CAAC;SACxE,CAAC,CAAC;IACL,CAAC;AACH,CAAC"}
|
|
@@ -1,77 +1,4 @@
|
|
|
1
|
-
//
|
|
2
|
-
//
|
|
3
|
-
|
|
4
|
-
// dependency on direct.
|
|
5
|
-
import * as path from "node:path";
|
|
6
|
-
import { CliError, EXIT_INPUT, EXIT_OK, sha256Text } from "../../common.js";
|
|
7
|
-
import { validateScriptV3 } from "../../domain/ingest/validation.js";
|
|
8
|
-
import { WorkspaceStore } from "../../infra/ingest/workspace-store.js";
|
|
9
|
-
import { LocalScriptOutputStore } from "../../infra/local-script-output-store.js";
|
|
10
|
-
import { remoteScriptOutputStoreFromEnv } from "../../infra/script-output-api.js";
|
|
11
|
-
import { ScriptOutputApiError, resolveOutputModeOrThrow } from "../../infra/script-output-store.js";
|
|
12
|
-
const strOf = (v) => (v === null || v === undefined ? "" : String(v));
|
|
13
|
-
function makeOutputStore(opts) {
|
|
14
|
-
const mode = resolveOutputModeOrThrow({ remote: opts["remote"], local: opts["local"], projectGroupNo: opts["project_group_no"] });
|
|
15
|
-
try {
|
|
16
|
-
return mode === "local"
|
|
17
|
-
? LocalScriptOutputStore.fromEnv(strOf(opts["workspace_path"]).trim() || undefined)
|
|
18
|
-
: remoteScriptOutputStoreFromEnv(strOf(opts["project_group_no"]).trim() || null);
|
|
19
|
-
}
|
|
20
|
-
catch (exc) {
|
|
21
|
-
throw new CliError("PUBLISH BLOCKED: output not configured", "Output store not configured.", {
|
|
22
|
-
exitCode: EXIT_INPUT,
|
|
23
|
-
errorCode: "SCRIPT_API_CONFIG_MISSING",
|
|
24
|
-
required: [mode === "local" ? "SCRIPTCTL_OUTPUT_DIR" : "gateway config (AWB_BASE_URL / ACCESS_KEY / project-group-no)"],
|
|
25
|
-
received: [exc instanceof Error ? exc.message : String(exc)],
|
|
26
|
-
nextSteps: ["Run `scriptctl doctor` to check output configuration."],
|
|
27
|
-
});
|
|
28
|
-
}
|
|
29
|
-
}
|
|
30
|
-
async function currentRevisionOrZero(client) {
|
|
31
|
-
try {
|
|
32
|
-
const revision = await client.getRevision();
|
|
33
|
-
return revision ? Number(revision["revision"] ?? 0) : 0;
|
|
34
|
-
}
|
|
35
|
-
catch {
|
|
36
|
-
return 0;
|
|
37
|
-
}
|
|
38
|
-
}
|
|
39
|
-
export async function commandPublish(opts) {
|
|
40
|
-
const workspacePath = strOf(opts["workspace_path"] || "workspace");
|
|
41
|
-
const store = new WorkspaceStore(path.resolve(workspacePath));
|
|
42
|
-
if (!store.has("script.json")) {
|
|
43
|
-
throw new CliError("PUBLISH BLOCKED: no script.json", "workspace has no script.json to publish.", {
|
|
44
|
-
exitCode: EXIT_INPUT, errorCode: "PUBLISH_NO_SCRIPT",
|
|
45
|
-
received: [store.path("script.json")],
|
|
46
|
-
nextSteps: ["Run `scriptctl ingest` first."],
|
|
47
|
-
});
|
|
48
|
-
}
|
|
49
|
-
const script = store.readJson("script.json");
|
|
50
|
-
const validation = validateScriptV3(script);
|
|
51
|
-
if (!validation.ok) {
|
|
52
|
-
throw new CliError("PUBLISH BLOCKED: v3 validation failed", "script.json does not pass v3 validation.", {
|
|
53
|
-
exitCode: EXIT_INPUT, errorCode: "PUBLISH_VALIDATION_FAILED",
|
|
54
|
-
received: validation.errors.slice(0, 5).map((e) => `${e.path}: ${e.message}`),
|
|
55
|
-
nextSteps: ["Re-run `scriptctl ingest` to regenerate a valid script.json."],
|
|
56
|
-
});
|
|
57
|
-
}
|
|
58
|
-
const client = makeOutputStore(opts);
|
|
59
|
-
const baseRevision = await currentRevisionOrZero(client);
|
|
60
|
-
const requestId = strOf(opts["request_id"]).trim() || `scriptctl-ingest:${sha256Text(JSON.stringify(script))}`;
|
|
61
|
-
let res;
|
|
62
|
-
try {
|
|
63
|
-
res = await client.replaceScript({ requestId, baseRevision, script, source: "ctl" });
|
|
64
|
-
}
|
|
65
|
-
catch (exc) {
|
|
66
|
-
if (exc instanceof ScriptOutputApiError) {
|
|
67
|
-
const conflict = /版本冲突|revision/i.test(exc.message);
|
|
68
|
-
throw new CliError("PUBLISH BLOCKED: write failed", conflict ? "Script updated by another revision; reload and retry." : exc.message, {
|
|
69
|
-
exitCode: EXIT_INPUT, errorCode: conflict ? "SCRIPT_REVISION_CONFLICT" : "SCRIPT_API_WRITE_FAILED",
|
|
70
|
-
received: [exc.message], nextSteps: conflict ? ["Re-run publish after reload."] : ["Check output config and retry."],
|
|
71
|
-
});
|
|
72
|
-
}
|
|
73
|
-
throw exc;
|
|
74
|
-
}
|
|
75
|
-
return [{ result: [`published rev ${baseRevision} → ${res["revision"]}; idempotent ${res["idempotent"] ?? false}`] }, EXIT_OK];
|
|
76
|
-
}
|
|
1
|
+
// Kept as an import-compatible name for internal callers. The public publish
|
|
2
|
+
// implementation has one source of truth: the managed local working-copy flow.
|
|
3
|
+
export { commandWorkingCopyPublish as commandPublish } from "../script/working-copy.js";
|
|
77
4
|
//# sourceMappingURL=publish-command.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"publish-command.js","sourceRoot":"","sources":["../../../src/usecases/ingest/publish-command.ts"],"names":[],"mappings":"AAAA,
|
|
1
|
+
{"version":3,"file":"publish-command.js","sourceRoot":"","sources":["../../../src/usecases/ingest/publish-command.ts"],"names":[],"mappings":"AAAA,6EAA6E;AAC7E,+EAA+E;AAC/E,OAAO,EAAE,yBAAyB,IAAI,cAAc,EAAE,MAAM,2BAA2B,CAAC"}
|
|
@@ -13,7 +13,13 @@ export async function commandContext(opts) {
|
|
|
13
13
|
errorCode: "ARGS_MISSING",
|
|
14
14
|
});
|
|
15
15
|
}
|
|
16
|
-
const template = contextTemplate(strOf(args[1]), {
|
|
16
|
+
const template = contextTemplate(strOf(args[1]), {
|
|
17
|
+
state: opts["state"],
|
|
18
|
+
clear: Boolean(opts["clear"]),
|
|
19
|
+
remove: Boolean(opts["remove"]),
|
|
20
|
+
append: Boolean(opts["append"]),
|
|
21
|
+
occurrence: opts["occurrence"],
|
|
22
|
+
});
|
|
17
23
|
return applySingleScriptOp(opts, { ...template, at: args[0] });
|
|
18
24
|
}
|
|
19
25
|
// ----- state change / transition --------------------------------------------
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"context.js","sourceRoot":"","sources":["../../../src/usecases/script/context.ts"],"names":[],"mappings":"AAKA,OAAO,EACL,QAAQ,EAKR,UAAU,GASX,MAAM,iBAAiB,CAAC;AA6BzB,OAAO,EACL,MAAM,EAIN,KAAK,GACN,MAAM,+BAA+B,CAAC;AAMvC,OAAO,EAC+I,mBAAmB,GACxK,MAAM,UAAU,CAAC;AAClB,OAAO,EAAE,eAAe,EAAE,MAAM,UAAU,CAAC;AAE3C,MAAM,CAAC,KAAK,UAAU,cAAc,CAAC,IAAU;IAC7C,MAAM,IAAI,GAAG,MAAM,CAAS,IAAI,CAAC,OAAO,CAAC,CAAC,CAAC;IAC3C,IAAI,IAAI,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QACpB,MAAM,IAAI,QAAQ,CAAC,oCAAoC,EAAE,uBAAuB,EAAE;YAChF,QAAQ,EAAE,UAAU;YACpB,QAAQ,EAAE,CAAC,2BAA2B,CAAC;YACvC,QAAQ,EAAE,IAAI;YACd,SAAS,EAAE,CAAC,yEAAyE,CAAC;YACtF,SAAS,EAAE,cAAc;SAC1B,CAAC,CAAC;IACL,CAAC;IACD,MAAM,QAAQ,GAAG,eAAe,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,EAAE,
|
|
1
|
+
{"version":3,"file":"context.js","sourceRoot":"","sources":["../../../src/usecases/script/context.ts"],"names":[],"mappings":"AAKA,OAAO,EACL,QAAQ,EAKR,UAAU,GASX,MAAM,iBAAiB,CAAC;AA6BzB,OAAO,EACL,MAAM,EAIN,KAAK,GACN,MAAM,+BAA+B,CAAC;AAMvC,OAAO,EAC+I,mBAAmB,GACxK,MAAM,UAAU,CAAC;AAClB,OAAO,EAAE,eAAe,EAAE,MAAM,UAAU,CAAC;AAE3C,MAAM,CAAC,KAAK,UAAU,cAAc,CAAC,IAAU;IAC7C,MAAM,IAAI,GAAG,MAAM,CAAS,IAAI,CAAC,OAAO,CAAC,CAAC,CAAC;IAC3C,IAAI,IAAI,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QACpB,MAAM,IAAI,QAAQ,CAAC,oCAAoC,EAAE,uBAAuB,EAAE;YAChF,QAAQ,EAAE,UAAU;YACpB,QAAQ,EAAE,CAAC,2BAA2B,CAAC;YACvC,QAAQ,EAAE,IAAI;YACd,SAAS,EAAE,CAAC,yEAAyE,CAAC;YACtF,SAAS,EAAE,cAAc;SAC1B,CAAC,CAAC;IACL,CAAC;IACD,MAAM,QAAQ,GAAG,eAAe,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,EAAE;QAC/C,KAAK,EAAE,IAAI,CAAC,OAAO,CAAC;QACpB,KAAK,EAAE,OAAO,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;QAC7B,MAAM,EAAE,OAAO,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;QAC/B,MAAM,EAAE,OAAO,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;QAC/B,UAAU,EAAE,IAAI,CAAC,YAAY,CAAC;KAC/B,CAAC,CAAC;IACH,OAAO,mBAAmB,CAAC,IAAI,EAAE,EAAE,GAAG,QAAQ,EAAE,EAAE,EAAE,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC;AACjE,CAAC;AAED,+EAA+E"}
|
|
@@ -1,64 +1,28 @@
|
|
|
1
|
-
import { CliError, EXIT_INPUT, EXIT_NEEDS_AGENT, EXIT_OK, exists,
|
|
1
|
+
import { CliError, EXIT_INPUT, EXIT_NEEDS_AGENT, EXIT_OK, exists, scriptJsonPath, } from "../../common.js";
|
|
2
|
+
import { atomicWriteJson } from "../../infra/script-working-copy.js";
|
|
2
3
|
import { blankScript } from "../../domain/script/lookups.js";
|
|
3
|
-
import { ScriptOutputApiError, } from "../../infra/script-output-store.js";
|
|
4
4
|
import { strOf, } from "../../domain/script/shared.js";
|
|
5
|
-
import { ScriptEditSession,
|
|
5
|
+
import { ScriptEditSession, validateSession, } from "./session.js";
|
|
6
6
|
import { blankCreateReport, } from "./lib.js";
|
|
7
7
|
export async function commandCreate(opts) {
|
|
8
8
|
const workspace = strOf(opts["workspace_path"] || "workspace");
|
|
9
9
|
const force = Boolean(opts["force"]);
|
|
10
10
|
const title = strOf(opts["title"]).trim();
|
|
11
11
|
const script = blankScript(title);
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
assertTargetCoherent(opts);
|
|
16
|
-
const localPath = strOf(opts["script_path"]).trim() || null;
|
|
17
|
-
if (localPath) {
|
|
18
|
-
if (exists(localPath) && !force) {
|
|
19
|
-
throw new CliError("CREATE BLOCKED: target already exists", "A script already exists at the target.", {
|
|
20
|
-
exitCode: EXIT_INPUT,
|
|
21
|
-
required: ["a non-existent target, or --force to overwrite"],
|
|
22
|
-
received: [localPath],
|
|
23
|
-
nextSteps: ["Edit the existing script with the atomic verbs, or pass --force to overwrite with a blank scaffold."],
|
|
24
|
-
errorCode: "SCRIPT_EXISTS",
|
|
25
|
-
});
|
|
26
|
-
}
|
|
27
|
-
writeJson(localPath, script);
|
|
28
|
-
const session = new ScriptEditSession({ workspace, scriptPath: localPath, script });
|
|
29
|
-
const validation = validateSession(session);
|
|
30
|
-
const passed = Boolean(validation["passed"]);
|
|
31
|
-
return [blankCreateReport(session, validation, null), passed ? EXIT_OK : EXIT_NEEDS_AGENT];
|
|
32
|
-
}
|
|
33
|
-
// DB mode: first write must be at revision 0. We never silently overwrite a
|
|
34
|
-
// populated DB script with a blank one — that would destroy work.
|
|
35
|
-
const client = scriptOutputClient(opts);
|
|
36
|
-
const baseRevision = await currentRevisionOrZero(client);
|
|
37
|
-
if (baseRevision > 0) {
|
|
38
|
-
throw new CliError("CREATE BLOCKED: DB script already exists", "A script already exists for this project.", {
|
|
12
|
+
const localPath = scriptJsonPath(opts);
|
|
13
|
+
if (exists(localPath) && !force) {
|
|
14
|
+
throw new CliError("CREATE BLOCKED: target already exists", "A script already exists at the target.", {
|
|
39
15
|
exitCode: EXIT_INPUT,
|
|
40
|
-
required: ["
|
|
41
|
-
received: [
|
|
42
|
-
nextSteps: ["Edit the existing script with the atomic verbs
|
|
16
|
+
required: ["a non-existent target, or --force to overwrite"],
|
|
17
|
+
received: [localPath],
|
|
18
|
+
nextSteps: ["Edit the existing script with the atomic verbs, or pass --force to overwrite with a blank scaffold."],
|
|
43
19
|
errorCode: "SCRIPT_EXISTS",
|
|
44
20
|
});
|
|
45
21
|
}
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
try {
|
|
49
|
-
res = await client.replaceScript({ requestId, baseRevision, script, source: "ctl" });
|
|
50
|
-
}
|
|
51
|
-
catch (exc) {
|
|
52
|
-
if (exc instanceof ScriptOutputApiError) {
|
|
53
|
-
throw apiErrorToCli("SCRIPT API BLOCKED: Create write failed", exc);
|
|
54
|
-
}
|
|
55
|
-
throw exc;
|
|
56
|
-
}
|
|
57
|
-
const revision = Number(res["revision"] ?? 0);
|
|
58
|
-
const session = new ScriptEditSession({ workspace, script, client, projectGroupNo: client.projectGroupNo, revision });
|
|
22
|
+
atomicWriteJson(localPath, script);
|
|
23
|
+
const session = new ScriptEditSession({ workspace, scriptPath: localPath, script });
|
|
59
24
|
const validation = validateSession(session);
|
|
60
|
-
await syncValidationResult(session, validation, revision);
|
|
61
25
|
const passed = Boolean(validation["passed"]);
|
|
62
|
-
return [blankCreateReport(session, validation,
|
|
26
|
+
return [blankCreateReport(session, validation, null), passed ? EXIT_OK : EXIT_NEEDS_AGENT];
|
|
63
27
|
}
|
|
64
28
|
//# sourceMappingURL=create.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"create.js","sourceRoot":"","sources":["../../../src/usecases/script/create.ts"],"names":[],"mappings":"AAKA,OAAO,EACL,QAAQ,EACR,UAAU,EACV,gBAAgB,EAChB,OAAO,EAIP,MAAM,
|
|
1
|
+
{"version":3,"file":"create.js","sourceRoot":"","sources":["../../../src/usecases/script/create.ts"],"names":[],"mappings":"AAKA,OAAO,EACL,QAAQ,EACR,UAAU,EACV,gBAAgB,EAChB,OAAO,EAIP,MAAM,EAGN,cAAc,GAGf,MAAM,iBAAiB,CAAC;AACzB,OAAO,EAAE,eAAe,EAAE,MAAM,oCAAoC,CAAC;AAErE,OAAO,EAAE,WAAW,EAAE,MAAM,gCAAgC,CAAC;AA2B7D,OAAO,EAKL,KAAK,GACN,MAAM,+BAA+B,CAAC;AACvC,OAAO,EACL,iBAAiB,EACE,eAAe,GAEnC,MAAM,cAAc,CAAC;AACtB,OAAO,EACib,iBAAiB,GACxc,MAAM,UAAU,CAAC;AAElB,MAAM,CAAC,KAAK,UAAU,aAAa,CAAC,IAAU;IAC5C,MAAM,SAAS,GAAG,KAAK,CAAC,IAAI,CAAC,gBAAgB,CAAC,IAAI,WAAW,CAAC,CAAC;IAC/D,MAAM,KAAK,GAAG,OAAO,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC,CAAC;IACrC,MAAM,KAAK,GAAG,KAAK,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC;IAC1C,MAAM,MAAM,GAAG,WAAW,CAAC,KAAK,CAAC,CAAC;IAElC,MAAM,SAAS,GAAG,cAAc,CAAC,IAAI,CAAC,CAAC;IACvC,IAAI,MAAM,CAAC,SAAS,CAAC,IAAI,CAAC,KAAK,EAAE,CAAC;QAChC,MAAM,IAAI,QAAQ,CAAC,uCAAuC,EAAE,wCAAwC,EAAE;YACpG,QAAQ,EAAE,UAAU;YACpB,QAAQ,EAAE,CAAC,gDAAgD,CAAC;YAC5D,QAAQ,EAAE,CAAC,SAAS,CAAC;YACrB,SAAS,EAAE,CAAC,qGAAqG,CAAC;YAClH,SAAS,EAAE,eAAe;SAC3B,CAAC,CAAC;IACL,CAAC;IACD,eAAe,CAAC,SAAS,EAAE,MAAM,CAAC,CAAC;IACnC,MAAM,OAAO,GAAG,IAAI,iBAAiB,CAAC,EAAE,SAAS,EAAE,UAAU,EAAE,SAAS,EAAE,MAAM,EAAE,CAAC,CAAC;IACpF,MAAM,UAAU,GAAG,eAAe,CAAC,OAAO,CAAC,CAAC;IAC5C,MAAM,MAAM,GAAG,OAAO,CAAC,UAAU,CAAC,QAAQ,CAAC,CAAC,CAAC;IAC7C,OAAO,CAAC,iBAAiB,CAAC,OAAO,EAAE,UAAU,EAAE,IAAI,CAAC,EAAE,MAAM,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,gBAAgB,CAAC,CAAC;AAC7F,CAAC"}
|
|
@@ -76,7 +76,7 @@ export const DO_BOOL_FLAGS = {
|
|
|
76
76
|
replace: new Set(["all", "regex"]),
|
|
77
77
|
transition: new Set(["clear"]),
|
|
78
78
|
emotion: new Set(["clear"]),
|
|
79
|
-
"scene-ref": new Set(["clear", "remove"]),
|
|
79
|
+
"scene-ref": new Set(["clear", "remove", "append"]),
|
|
80
80
|
delete: new Set(["force"]),
|
|
81
81
|
extend: new Set(["clear", "json-value"]),
|
|
82
82
|
};
|
|
@@ -242,11 +242,32 @@ export function contextTemplate(target, f) {
|
|
|
242
242
|
nextSteps: ["Pick one and retry."], errorCode: "CONTEXT_FLAG_CONFLICT",
|
|
243
243
|
});
|
|
244
244
|
}
|
|
245
|
+
const append = Boolean(f.append);
|
|
246
|
+
const occurrenceRaw = strOf(f.occurrence).trim();
|
|
247
|
+
const occurrence = occurrenceRaw ? Number(occurrenceRaw) : undefined;
|
|
248
|
+
if (occurrence !== undefined && (!Number.isInteger(occurrence) || occurrence < 1)) {
|
|
249
|
+
throw new CliError("VERB BLOCKED: scene-ref occurrence invalid", "scene-ref: --occurrence must be a positive integer.", {
|
|
250
|
+
exitCode: EXIT_USAGE,
|
|
251
|
+
required: ["--occurrence <positive integer> (1-based)"],
|
|
252
|
+
received: [occurrenceRaw],
|
|
253
|
+
nextSteps: ["Use 1 for the first matching scene ref, 2 for the second, and so on."],
|
|
254
|
+
errorCode: "SCENE_REF_OCCURRENCE_INVALID",
|
|
255
|
+
});
|
|
256
|
+
}
|
|
257
|
+
if (append && (!stateSet || occurrence !== undefined)) {
|
|
258
|
+
throw new CliError("VERB BLOCKED: scene-ref append flags invalid", "scene-ref: --append requires --state and cannot be combined with --occurrence.", {
|
|
259
|
+
exitCode: EXIT_USAGE,
|
|
260
|
+
required: ["--state <state_id> --append"],
|
|
261
|
+
received: [append ? "--append" : "", occurrence !== undefined ? "--occurrence" : "", clearSet ? "--clear" : "", removeSet ? "--remove" : ""].filter(Boolean),
|
|
262
|
+
nextSteps: ["Append a new actor ref with --state <state_id> --append, or target an existing ref with --occurrence <n>."],
|
|
263
|
+
errorCode: "SCENE_REF_APPEND_FLAG_CONFLICT",
|
|
264
|
+
});
|
|
265
|
+
}
|
|
245
266
|
if (removeSet)
|
|
246
|
-
return { op: "scene.ref.remove", target };
|
|
267
|
+
return { op: "scene.ref.remove", target, occurrence };
|
|
247
268
|
if (clearSet)
|
|
248
|
-
return { op: "scene.ref.clear", target };
|
|
249
|
-
return { op: "scene.ref.set", target, state: f.state === "none" ? "" : f.state };
|
|
269
|
+
return { op: "scene.ref.clear", target, occurrence };
|
|
270
|
+
return { op: "scene.ref.set", target, state: f.state === "none" ? "" : f.state, append, occurrence };
|
|
250
271
|
}
|
|
251
272
|
// v3 dialogue speaker: a single inline speaker — an actor, OR a non-actor kind
|
|
252
273
|
// (system|broadcast|offscreen|group) with an optional label.
|
|
@@ -302,7 +323,16 @@ export function lineToOp(verb, args, flags) {
|
|
|
302
323
|
case "emotion":
|
|
303
324
|
return { ...emotionTemplate({ emotion: args[1], clear: Boolean(flags["clear"]) }), at: a0 };
|
|
304
325
|
case "scene-ref":
|
|
305
|
-
return {
|
|
326
|
+
return {
|
|
327
|
+
...contextTemplate(a1, {
|
|
328
|
+
state: flags["state"],
|
|
329
|
+
clear: Boolean(flags["clear"]),
|
|
330
|
+
remove: Boolean(flags["remove"]),
|
|
331
|
+
append: Boolean(flags["append"]),
|
|
332
|
+
occurrence: flags["occurrence"],
|
|
333
|
+
}),
|
|
334
|
+
at: a0,
|
|
335
|
+
};
|
|
306
336
|
case "dialogue":
|
|
307
337
|
return { ...dialogueTemplate({ actor: flags["actor"], kind: flags["kind"], label: flags["label"] }), at: a0 };
|
|
308
338
|
case "rename":
|