@telepath-computer/television 0.1.157 → 0.1.158
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.cjs
CHANGED
|
@@ -48121,6 +48121,16 @@ function hasTrailingSeparator(value) {
|
|
|
48121
48121
|
const last = value.at(-1);
|
|
48122
48122
|
return last === "/" || last === "\\";
|
|
48123
48123
|
}
|
|
48124
|
+
function stripTrailingSeparators(value) {
|
|
48125
|
+
let end = value.length;
|
|
48126
|
+
while (end > 1 && (value[end - 1] === "/" || value[end - 1] === "\\")) {
|
|
48127
|
+
end -= 1;
|
|
48128
|
+
}
|
|
48129
|
+
if (end === 2 && end < value.length && /^[A-Za-z]:$/.test(value.slice(0, 2))) {
|
|
48130
|
+
end += 1;
|
|
48131
|
+
}
|
|
48132
|
+
return value.slice(0, end);
|
|
48133
|
+
}
|
|
48124
48134
|
function artifactBasename(value) {
|
|
48125
48135
|
const slash = value.lastIndexOf("/");
|
|
48126
48136
|
const backslash = value.lastIndexOf("\\");
|
|
@@ -50374,8 +50384,7 @@ var ServerStore = class extends EventTarget {
|
|
|
50374
50384
|
if (input.fields.url !== void 0) {
|
|
50375
50385
|
throw new InvalidRequestError("artifact patch cannot set both path and url");
|
|
50376
50386
|
}
|
|
50377
|
-
const artifactPath = input.fields.path.trim();
|
|
50378
|
-
this.validateArtifactPath(artifactPath);
|
|
50387
|
+
const artifactPath = this.normalizeArtifactPath(input.fields.path.trim());
|
|
50379
50388
|
pointerChanged = artifactPath !== artifact.path;
|
|
50380
50389
|
updated = { ...updated, path: artifactPath };
|
|
50381
50390
|
}
|
|
@@ -50752,8 +50761,7 @@ var ServerStore = class extends EventTarget {
|
|
|
50752
50761
|
if (input.url !== void 0) {
|
|
50753
50762
|
throw new InvalidRequestError("path artifacts cannot set url");
|
|
50754
50763
|
}
|
|
50755
|
-
const artifactPath = input.path.trim();
|
|
50756
|
-
this.validateArtifactPath(artifactPath);
|
|
50764
|
+
const artifactPath = this.normalizeArtifactPath(input.path.trim());
|
|
50757
50765
|
return createArtifact({ ...input.id ? { id: input.id } : {}, kind: "path", title: input.title, path: artifactPath });
|
|
50758
50766
|
}
|
|
50759
50767
|
case "url": {
|
|
@@ -50771,32 +50779,40 @@ var ServerStore = class extends EventTarget {
|
|
|
50771
50779
|
}
|
|
50772
50780
|
}
|
|
50773
50781
|
}
|
|
50774
|
-
|
|
50782
|
+
/**
|
|
50783
|
+
* Classify the supplied path by what is on disk and return the canonical
|
|
50784
|
+
* form to persist: directory paths always end with a trailing separator,
|
|
50785
|
+
* file paths never do. Callers may supply either form; the trailing
|
|
50786
|
+
* separator on the stored string is a server-maintained invariant that
|
|
50787
|
+
* routing (proxy, watcher, markdown gating, client dispatch) relies on
|
|
50788
|
+
* without statting.
|
|
50789
|
+
*/
|
|
50790
|
+
normalizeArtifactPath(artifactPath) {
|
|
50775
50791
|
if (!import_node_path11.default.isAbsolute(artifactPath)) {
|
|
50776
50792
|
throw new InvalidRequestError("path must be absolute");
|
|
50777
50793
|
}
|
|
50794
|
+
const stripped = stripTrailingSeparators(artifactPath);
|
|
50778
50795
|
let stat;
|
|
50779
50796
|
try {
|
|
50780
|
-
(0, import_node_fs9.accessSync)(
|
|
50781
|
-
stat = (0, import_node_fs9.statSync)(
|
|
50797
|
+
(0, import_node_fs9.accessSync)(stripped, import_node_fs9.constants.R_OK);
|
|
50798
|
+
stat = (0, import_node_fs9.statSync)(stripped);
|
|
50782
50799
|
} catch {
|
|
50783
50800
|
throw new InvalidRequestError(`path does not exist or is not readable: ${artifactPath}`);
|
|
50784
50801
|
}
|
|
50785
|
-
if (
|
|
50786
|
-
|
|
50787
|
-
|
|
50802
|
+
if (stat.isDirectory()) {
|
|
50803
|
+
const canonical = hasTrailingSeparator(stripped) ? stripped : `${stripped}${import_node_path11.default.sep}`;
|
|
50804
|
+
if (!DIRECTORY_INDEX_BASENAMES.some((basename) => (0, import_node_fs9.existsSync)(import_node_path11.default.join(canonical, basename)))) {
|
|
50805
|
+
throw new InvalidRequestError(`directory artifact must contain index.html or index.htm: ${canonical}`);
|
|
50788
50806
|
}
|
|
50789
|
-
|
|
50790
|
-
throw new InvalidRequestError(`directory artifact must contain index.html or index.htm: ${artifactPath}`);
|
|
50791
|
-
}
|
|
50792
|
-
return;
|
|
50807
|
+
return canonical;
|
|
50793
50808
|
}
|
|
50794
50809
|
if (!stat.isFile()) {
|
|
50795
|
-
throw new InvalidRequestError(`
|
|
50810
|
+
throw new InvalidRequestError(`path must resolve to a regular file or directory: ${artifactPath}`);
|
|
50796
50811
|
}
|
|
50797
|
-
if (!isAllowedArtifactFilePath(
|
|
50798
|
-
throw new InvalidRequestError(`path extension must be one of .md, .markdown, .htm, .html: ${
|
|
50812
|
+
if (!isAllowedArtifactFilePath(stripped)) {
|
|
50813
|
+
throw new InvalidRequestError(`path extension must be one of .md, .markdown, .htm, .html: ${stripped}`);
|
|
50799
50814
|
}
|
|
50815
|
+
return stripped;
|
|
50800
50816
|
}
|
|
50801
50817
|
canInstallOnboardingArtifact() {
|
|
50802
50818
|
return !(0, import_node_fs9.existsSync)(getOnboardingArtifactSentinelPath(this.storagePath)) && !this._artifacts.has(ONBOARDING_ARTIFACT_ID) && this.onboardingArtifactSourcePath !== void 0;
|
|
@@ -51045,8 +51061,8 @@ function resolveVercelSkillsInstallerBin() {
|
|
|
51045
51061
|
return localRequire.resolve("skills/bin/cli.mjs");
|
|
51046
51062
|
}
|
|
51047
51063
|
function readCLIVersion() {
|
|
51048
|
-
if ("0.1.
|
|
51049
|
-
return "0.1.
|
|
51064
|
+
if ("0.1.158".length > 0) {
|
|
51065
|
+
return "0.1.158";
|
|
51050
51066
|
}
|
|
51051
51067
|
const devPackageJsonPath = import_node_path12.default.join(getDevPackageDir(), "package.json");
|
|
51052
51068
|
if (!(0, import_node_fs10.existsSync)(devPackageJsonPath)) {
|
|
@@ -51506,8 +51522,8 @@ function createProgram(env, argv = []) {
|
|
|
51506
51522
|
});
|
|
51507
51523
|
});
|
|
51508
51524
|
program2.command("create-path-artifact").description(
|
|
51509
|
-
"Create a path artifact that points at an existing absolute markdown or HTML file, or at a directory
|
|
51510
|
-
).requiredOption("--screen <id>", "Target screen ID").requiredOption("--title <title>", "Artifact title").requiredOption("--path <path>", "Absolute path to an existing markdown/HTML file or indexed directory").option("--focus-artifact", "Focus the new artifact after creation").option("--no-focus", "Create the artifact in the background without changing focus").option("--port <number>", "Server port", parsePortOption).option("--storage-path <path>", "Directory containing the Television token").addHelpText("after", buildArtifactWorkflowHelpNote(true)).action(async (opts) => {
|
|
51525
|
+
"Create a path artifact that points at an existing absolute markdown or HTML file, or at a directory with a root index.html/index.htm (trailing separator optional; the server detects file vs directory on disk). Television records the pointer only; HTML and directory targets are read-only, and markdown targets are written through only by in-UI editor saves via PUT /markdown/<id>."
|
|
51526
|
+
).requiredOption("--screen <id>", "Target screen ID").requiredOption("--title <title>", "Artifact title").requiredOption("--path <path>", "Absolute path to an existing markdown/HTML file or indexed directory (trailing separator optional)").option("--focus-artifact", "Focus the new artifact after creation").option("--no-focus", "Create the artifact in the background without changing focus").option("--port <number>", "Server port", parsePortOption).option("--storage-path <path>", "Directory containing the Television token").addHelpText("after", buildArtifactWorkflowHelpNote(true)).action(async (opts) => {
|
|
51511
51527
|
const shouldFocus = resolveFocusDirective(argv, "create-path-artifact", "--focus-artifact");
|
|
51512
51528
|
const artifactPath = opts.path.trim();
|
|
51513
51529
|
const client = createAuthenticatedClient(opts);
|
|
@@ -51544,10 +51560,21 @@ function createProgram(env, argv = []) {
|
|
|
51544
51560
|
writeJSON(env.stdout, { storagePath: getTelevisionStoragePath() });
|
|
51545
51561
|
});
|
|
51546
51562
|
program2.command("update-artifact").description(
|
|
51547
|
-
"Update artifact metadata in place
|
|
51548
|
-
).requiredOption("--id <id>", "Artifact ID").
|
|
51563
|
+
"Update artifact metadata in place: --title on any artifact, --path to repoint a path artifact, --url to repoint a URL artifact. ID and kind are immutable. The server validates the new pointer; for path artifacts the target must exist (trailing separator optional) and the content watcher follows it."
|
|
51564
|
+
).requiredOption("--id <id>", "Artifact ID").option("--title <title>", "New title").option("--path <path>", "New absolute path for a path artifact: markdown/HTML file or indexed directory (trailing separator optional)").option("--url <url>", "New http(s) URL for a URL artifact").option("--port <number>", "Server port", parsePortOption).option("--storage-path <path>", "Directory containing the Television token").action(async (opts) => {
|
|
51565
|
+
if (opts.title === void 0 && opts.path === void 0 && opts.url === void 0) {
|
|
51566
|
+
throw createDirectiveError("tv update-artifact requires at least one of --title, --path, or --url.");
|
|
51567
|
+
}
|
|
51568
|
+
if (opts.path !== void 0 && opts.url !== void 0) {
|
|
51569
|
+
throw createDirectiveError("tv update-artifact accepts --path or --url, not both; an artifact's kind is immutable.");
|
|
51570
|
+
}
|
|
51549
51571
|
const client = createAuthenticatedClient(opts);
|
|
51550
|
-
await client.artifacts.update({
|
|
51572
|
+
await client.artifacts.update({
|
|
51573
|
+
artifactID: opts.id,
|
|
51574
|
+
...opts.title !== void 0 ? { title: opts.title } : {},
|
|
51575
|
+
...opts.path !== void 0 ? { path: opts.path.trim() } : {},
|
|
51576
|
+
...opts.url !== void 0 ? { url: opts.url.trim() } : {}
|
|
51577
|
+
});
|
|
51551
51578
|
writeLine(env.stdout, `Artifact ${opts.id} updated.`);
|
|
51552
51579
|
});
|
|
51553
51580
|
program2.command("delete-artifact").description(
|
|
@@ -113,7 +113,7 @@ Commands group into four intents:
|
|
|
113
113
|
|
|
114
114
|
- **Screen and display commands** — create, inspect, remove, or switch screens, or change the active display theme (`create-screen`, `list-screens`, `get-screen`, `remove-screen`, `focus-screen`, `focus-status`, `set-theme`).
|
|
115
115
|
- **Artifact creation commands** — register path or URL artifacts (`create-path-artifact`, `create-url-artifact`).
|
|
116
|
-
- **Artifact management commands** — inspect, retitle, focus, list, or delete existing artifacts (`delete-artifact`, `get-artifact`, `list-artifacts`, `update-artifact`, `focus-artifact`).
|
|
116
|
+
- **Artifact management commands** — inspect, retitle, repoint, focus, list, or delete existing artifacts (`delete-artifact`, `get-artifact`, `list-artifacts`, `update-artifact`, `focus-artifact`).
|
|
117
117
|
- **Server and environment commands** — operate on the Television server itself (`serve`, `status`, `stop`, `storage-path`, `skills install`).
|
|
118
118
|
|
|
119
119
|
When the CLI rejects a command, follow the directive it prints rather than guessing flags.
|
|
@@ -270,9 +270,9 @@ Always tell the user where you put the file.
|
|
|
270
270
|
|
|
271
271
|
- **Single markdown file** ending in `.md` or `.markdown`
|
|
272
272
|
- **Single HTML file** ending in `.htm` or `.html`
|
|
273
|
-
- **HTML directory** — a
|
|
273
|
+
- **HTML directory** — a directory whose root contains `index.html` or `index.htm`, plus any sibling assets
|
|
274
274
|
|
|
275
|
-
The path must be absolute, existing, and readable by the server.
|
|
275
|
+
The path must be absolute, existing, and readable by the server. A trailing separator is optional — the server checks the path on disk to decide whether it is a file or a directory.
|
|
276
276
|
|
|
277
277
|
## Authoring quality
|
|
278
278
|
|
|
@@ -348,10 +348,10 @@ Single-file example:
|
|
|
348
348
|
tv create-path-artifact --screen "<screen-id>" --title "Artifact title" --path /absolute/path/to/report.html --focus-artifact
|
|
349
349
|
```
|
|
350
350
|
|
|
351
|
-
Directory example:
|
|
351
|
+
Directory example (trailing slash optional):
|
|
352
352
|
|
|
353
353
|
```bash
|
|
354
|
-
tv create-path-artifact --screen "<screen-id>" --title "Artifact title" --path /absolute/path/to/dashboard
|
|
354
|
+
tv create-path-artifact --screen "<screen-id>" --title "Artifact title" --path /absolute/path/to/dashboard --focus-artifact
|
|
355
355
|
```
|
|
356
356
|
|
|
357
357
|
A directory artifact needs root `index.html` or `index.htm`. Keep sibling assets relative so they resolve through the artifact proxy:
|
|
@@ -401,6 +401,15 @@ To retitle an artifact:
|
|
|
401
401
|
tv update-artifact --id "<artifact-id>" --title "New title"
|
|
402
402
|
```
|
|
403
403
|
|
|
404
|
+
To repoint an artifact at different content (same kind only — a path artifact takes `--path`, a URL artifact takes `--url`):
|
|
405
|
+
|
|
406
|
+
```bash
|
|
407
|
+
tv update-artifact --id "<artifact-id>" --path /absolute/path/to/new-target
|
|
408
|
+
tv update-artifact --id "<artifact-id>" --url "https://example.com/next"
|
|
409
|
+
```
|
|
410
|
+
|
|
411
|
+
The new path follows the same rules as creation (file or indexed directory, trailing separator optional). Rendering follows the new pointer immediately, and for path artifacts the content watcher retargets with it. Prefer repointing over delete-and-recreate when the artifact should keep its identity and screen placement.
|
|
412
|
+
|
|
404
413
|
Artifact repositioning on its current screen is a browser UI drag/drop gesture; the CLI does not expose layout mutation today.
|
|
405
414
|
|
|
406
415
|
To move the same underlying path or URL to another screen, delete the existing artifact and create a new one on the target screen with the same `--path` or `--url`.
|