dsh-claude-motion 2.9.2 → 2.10.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/README.md +12 -11
- package/cordis.patch.yml +8 -2
- package/lib/index.js +28 -753
- package/package.json +4 -18
- package/skills/claude-motion/SKILL.md +3 -3
- package/skills/claude-motion/scripts/artifact.mjs +11 -8
- package/lib/client.js +0 -1800
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "dsh-claude-motion",
|
|
3
|
-
"version": "2.
|
|
3
|
+
"version": "2.10.1",
|
|
4
4
|
"description": "DeepSeek Harness plugin: the claude-motion skill from baoyu-design. The agent writes short animated films as code, scene by scene, and plays them in a local Motion player that exports MP4 or GIF.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"dsh",
|
|
@@ -24,7 +24,6 @@
|
|
|
24
24
|
"icon": "./icon.svg",
|
|
25
25
|
"exports": {
|
|
26
26
|
".": "./lib/index.js",
|
|
27
|
-
"./client": "./lib/client.js",
|
|
28
27
|
"./cordis.patch.yml": "./cordis.patch.yml",
|
|
29
28
|
"./locale/*.json": "./locale/*.json",
|
|
30
29
|
"./package.json": "./package.json"
|
|
@@ -44,25 +43,12 @@
|
|
|
44
43
|
"node": ">=20",
|
|
45
44
|
"dsh": ">=0.2.0-0"
|
|
46
45
|
},
|
|
46
|
+
"dependencies": {
|
|
47
|
+
"dsh-claude-artifacts": "^2.10.1"
|
|
48
|
+
},
|
|
47
49
|
"dsh": {
|
|
48
50
|
"bundle": {
|
|
49
51
|
"patch": "./cordis.patch.yml"
|
|
50
|
-
},
|
|
51
|
-
"client": {
|
|
52
|
-
"platform": "web",
|
|
53
|
-
"inject": [
|
|
54
|
-
"@deepseek-ai/dsh-api-session-controller",
|
|
55
|
-
"@deepseek-ai/dsh-api-workspace-controller",
|
|
56
|
-
"@deepseek-ai/dsh-client-connection",
|
|
57
|
-
"@deepseek-ai/dsh-client-locale",
|
|
58
|
-
"@deepseek-ai/dsh-client-ui-chat",
|
|
59
|
-
"@deepseek-ai/dsh-client-ui-conversation",
|
|
60
|
-
"@deepseek-ai/dsh-client-ui-layout",
|
|
61
|
-
"@deepseek-ai/dsh-client-ui-renderer",
|
|
62
|
-
"@deepseek-ai/dsh-client-ui-sidebar",
|
|
63
|
-
"@deepseek-ai/dsh-client-ui-sidebar-right",
|
|
64
|
-
"@deepseek-ai/dsh-client-ui-workspace"
|
|
65
|
-
]
|
|
66
52
|
}
|
|
67
53
|
}
|
|
68
54
|
}
|
|
@@ -75,7 +75,7 @@ below, `A` is `<this skill's folder>/scripts/artifact.mjs`.
|
|
|
75
75
|
| `node $A serve <root> [--port n] [--lan]` / `stop <root>` | The same server in the foreground / takes this folder off the server, which ends with the last one. |
|
|
76
76
|
| `node $A share <root>` | Opens it to the local network and prints a link per role; `--disable` / `--enable` / `--reset <role>`, `--role <guest>=<role>`, `--off`. See Sharing. |
|
|
77
77
|
| `node $A comments <root>` / `comment-reply` / `comment-resolve` | The comments people leave in the open player, and your answers: Comments, below. |
|
|
78
|
-
| `node $A archive <root> [--out file.zip\|dir]` | The whole folder, history and comments too, as one zip beside it (`--out`: another file or folder), to back it up, move it to another computer or send it to someone: `{file, files, bytes, open}`. Unzipped anywhere, `open` carries on. The owner's Download folder button in the page does the same; the server's own files
|
|
78
|
+
| `node $A archive <root> [--out file.zip\|dir]` | The whole folder, history and comments too, as one zip beside it (`--out`: another file or folder), to back it up, move it to another computer or send it to someone: `{file, files, bytes, open}`. Unzipped anywhere, `open` carries on. The owner's Download folder button in the page does the same; the server's own files, the share links, `exports/` and `.git` stay out. |
|
|
79
79
|
| `node $A list [dir …]` | The design systems in the current directory (or the folders given, and those in `$CLAUDE_DESIGN_SYSTEMS`), each `{title, root, tokens}`. |
|
|
80
80
|
|
|
81
81
|
- **A batch** is a JSON array (or `{"writes": [...]}`) of
|
|
@@ -670,10 +670,10 @@ changed which document, and when.
|
|
|
670
670
|
|
|
671
671
|
`open` writes `<root>/.gitignore` when the folder has none. It leaves out what only this computer's server needs:
|
|
672
672
|
`.artifact-server.json`, `.artifact-server.log`, `.sharing.json` (the share links), `history/` (the versions; git
|
|
673
|
-
keeps its own), save temp files and `.DS_Store`. Everything else, `project/` and `comments.json` included, is the
|
|
673
|
+
keeps its own), `exports/` (saved downloads and renders), save temp files and `.DS_Store`. Everything else, `project/` and `comments.json` included, is the
|
|
674
674
|
film and goes in git. A `.gitignore` already there is the person's: leave it. Moving or backing up the film is
|
|
675
675
|
copying or cloning the folder (`archive` puts it,
|
|
676
|
-
history included, in one zip); `open` there starts it again.
|
|
676
|
+
history included and `.git` not, in one zip); `open` there starts it again.
|
|
677
677
|
|
|
678
678
|
Commit, push or set up git only when asked. Asked to check the film before each commit: write
|
|
679
679
|
`.git/hooks/pre-commit` (and `chmod +x` it) in the repository that holds `<root>`, with this skill's folder as an
|
|
@@ -51,7 +51,7 @@ function removeState(root) {
|
|
|
51
51
|
fs.rmSync(path.join(root, STATE_FILE), { force: true });
|
|
52
52
|
}
|
|
53
53
|
var GITIGNORE_FILE = ".gitignore";
|
|
54
|
-
var gitignoreLines = (kind) => [STATE_FILE, LOG_FILE, ".sharing.json", ...kind === "docs" ? [] : ["history/"], "
|
|
54
|
+
var gitignoreLines = (kind) => [STATE_FILE, LOG_FILE, ".sharing.json", ...kind === "docs" ? [] : ["/history/"], `/${EXPORTS_DIR}/`, "*.tmp", ".tmp-*", ".DS_Store"];
|
|
55
55
|
function writeGitignore(root, kind) {
|
|
56
56
|
const file = path.join(root, GITIGNORE_FILE);
|
|
57
57
|
try {
|
|
@@ -104,15 +104,17 @@ function isTailnet(address) {
|
|
|
104
104
|
const m = /^100\.(\d{1,3})\./.exec(address);
|
|
105
105
|
return !!m && Number(m[1]) >= 64 && Number(m[1]) <= 127;
|
|
106
106
|
}
|
|
107
|
+
var isTunnel = (name) => /^(utun|tun|tap|wg|ppp|ipsec)\d/i.test(name);
|
|
107
108
|
function lanAddresses() {
|
|
108
|
-
const out =
|
|
109
|
-
for (const list of Object.
|
|
109
|
+
const out = /* @__PURE__ */ new Map();
|
|
110
|
+
for (const [name, list] of Object.entries(os.networkInterfaces())) {
|
|
110
111
|
for (const entry of list ?? []) {
|
|
111
112
|
if (entry.family !== "IPv4" || entry.internal || entry.address.startsWith("169.254.") || isBenchmarkRange(entry.address)) continue;
|
|
112
|
-
|
|
113
|
+
const rank = isTailnet(entry.address) ? 2 : isTunnel(name) ? 1 : 0;
|
|
114
|
+
out.set(entry.address, Math.min(rank, out.get(entry.address) ?? rank));
|
|
113
115
|
}
|
|
114
116
|
}
|
|
115
|
-
return [...
|
|
117
|
+
return [...out.keys()].sort((a, b) => out.get(a) - out.get(b));
|
|
116
118
|
}
|
|
117
119
|
function answers(host, port) {
|
|
118
120
|
return new Promise((resolve) => {
|
|
@@ -695,8 +697,9 @@ var Hub = class {
|
|
|
695
697
|
}
|
|
696
698
|
// ---- the network side ------------------------------------------------------------------------------------------
|
|
697
699
|
async openLan() {
|
|
698
|
-
|
|
699
|
-
|
|
700
|
+
const addresses = lanAddresses().filter((address) => !this.lanServers.has(address));
|
|
701
|
+
const answering = await Promise.all(addresses.map(answersAnyPort));
|
|
702
|
+
for (const address of addresses.filter((_, i) => !answering[i])) {
|
|
700
703
|
const server = this.createServer();
|
|
701
704
|
try {
|
|
702
705
|
await listen(server, this.port, address);
|
|
@@ -1018,7 +1021,7 @@ import { promisify } from "node:util";
|
|
|
1018
1021
|
import zlib from "node:zlib";
|
|
1019
1022
|
var LOCAL_FILES = /* @__PURE__ */ new Set([STATE_FILE, LOG_FILE, SHARING_FILE]);
|
|
1020
1023
|
var LOCAL_DIRS = /* @__PURE__ */ new Set([EXPORTS_DIR]);
|
|
1021
|
-
var JUNK_FILES = /* @__PURE__ */ new Set([".DS_Store", "Thumbs.db", "desktop.ini"]);
|
|
1024
|
+
var JUNK_FILES = /* @__PURE__ */ new Set([".DS_Store", "Thumbs.db", "desktop.ini", ".git"]);
|
|
1022
1025
|
var isTemp = (name) => name.endsWith(".tmp") || name.startsWith(".tmp-");
|
|
1023
1026
|
var STORED = /* @__PURE__ */ new Set([".png", ".jpg", ".jpeg", ".gif", ".webp", ".avif", ".heic", ".mp4", ".m4v", ".mov", ".webm", ".mp3", ".m4a", ".aac", ".ogg", ".opus", ".flac", ".woff", ".woff2", ".zip", ".gz", ".br", ".zst", ".7z"]);
|
|
1024
1027
|
var MAX_ENTRIES = 65535;
|