orizu 0.5.38 → 0.5.40
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 +95 -3
- package/dist/app-commands.d.ts.map +1 -1
- package/dist/app-commands.js +215 -57
- package/dist/app-publish-failure.d.ts +6 -0
- package/dist/app-publish-failure.d.ts.map +1 -0
- package/dist/app-publish-failure.js +9 -0
- package/dist/app-publish-paths.d.ts +4 -0
- package/dist/app-publish-paths.d.ts.map +1 -0
- package/dist/app-publish-paths.js +32 -0
- package/dist/app-publish-workspace.d.ts +16 -0
- package/dist/app-publish-workspace.d.ts.map +1 -0
- package/dist/app-publish-workspace.js +175 -0
- package/dist/artifacts-git-runtime.d.ts +5 -0
- package/dist/artifacts-git-runtime.d.ts.map +1 -1
- package/dist/artifacts-git-runtime.js +70 -25
- package/dist/artifacts-session-merge.d.ts +62 -0
- package/dist/artifacts-session-merge.d.ts.map +1 -0
- package/dist/artifacts-session-merge.js +123 -0
- package/dist/dataset-append-workflow.d.ts +12 -0
- package/dist/dataset-append-workflow.d.ts.map +1 -0
- package/dist/dataset-append-workflow.js +198 -0
- package/dist/dataset-commands.d.ts +3 -1
- package/dist/dataset-commands.d.ts.map +1 -1
- package/dist/dataset-commands.js +111 -191
- package/dist/dataset-delete-workflow.d.ts +4 -0
- package/dist/dataset-delete-workflow.d.ts.map +1 -0
- package/dist/dataset-delete-workflow.js +75 -0
- package/dist/dataset-lock-workflow.d.ts +12 -0
- package/dist/dataset-lock-workflow.d.ts.map +1 -0
- package/dist/dataset-lock-workflow.js +76 -0
- package/dist/dataset-readme-workflow.d.ts +13 -0
- package/dist/dataset-readme-workflow.d.ts.map +1 -0
- package/dist/dataset-readme-workflow.js +82 -0
- package/dist/dataset-row-workflow.d.ts +14 -0
- package/dist/dataset-row-workflow.d.ts.map +1 -0
- package/dist/dataset-row-workflow.js +202 -0
- package/dist/dataset-split-reads.d.ts +28 -0
- package/dist/dataset-split-reads.d.ts.map +1 -0
- package/dist/dataset-split-reads.js +47 -0
- package/dist/dataset-transfer-download.js +6 -6
- package/dist/dataset-transfer-upload.js +8 -8
- package/dist/git-credential.d.ts +1 -1
- package/dist/git-credential.d.ts.map +1 -1
- package/dist/git-credential.js +8 -1
- package/dist/help.d.ts.map +1 -1
- package/dist/help.js +32 -6
- package/dist/hosted-boot.d.ts +12 -0
- package/dist/hosted-boot.d.ts.map +1 -1
- package/dist/hosted-boot.js +63 -1
- package/dist/hosted-harness-opencode.d.ts +4 -5
- package/dist/hosted-harness-opencode.d.ts.map +1 -1
- package/dist/hosted-harness-opencode.js +66 -52
- package/dist/hosted-loop-lifecycle.d.ts +4 -10
- package/dist/hosted-loop-lifecycle.d.ts.map +1 -1
- package/dist/hosted-loop-lifecycle.js +4 -10
- package/dist/hosted-loop.d.ts +2 -0
- package/dist/hosted-loop.d.ts.map +1 -1
- package/dist/hosted-loop.js +5 -4
- package/dist/hosted-session-cli.d.ts.map +1 -1
- package/dist/hosted-session-cli.js +6 -1
- package/dist/hosted-session-seed.d.ts +45 -0
- package/dist/hosted-session-seed.d.ts.map +1 -0
- package/dist/hosted-session-seed.js +61 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +9 -1
- package/dist/instruction-delivery.d.ts +14 -0
- package/dist/instruction-delivery.d.ts.map +1 -0
- package/dist/instruction-delivery.js +103 -0
- package/dist/instruction-set-sync/index.d.ts +17 -0
- package/dist/instruction-set-sync/index.d.ts.map +1 -1
- package/dist/instruction-set-sync/index.js +44 -17
- package/dist/instruction-set-update/index.d.ts +2 -2
- package/dist/instruction-set-update/index.d.ts.map +1 -1
- package/dist/instruction-set-update/index.js +2 -2
- package/dist/instruction-sets-cli.d.ts.map +1 -1
- package/dist/instruction-sets-cli.js +19 -27
- package/dist/json-response.d.ts +1 -0
- package/dist/json-response.d.ts.map +1 -1
- package/dist/json-response.js +7 -0
- package/dist/jsonl-stream.d.ts +1 -0
- package/dist/jsonl-stream.d.ts.map +1 -1
- package/dist/jsonl-stream.js +7 -0
- package/dist/preview-runtime.d.ts +2 -2
- package/dist/preview-runtime.d.ts.map +1 -1
- package/dist/preview-runtime.js +37 -7
- package/dist/provider-list-workflow.d.ts +3 -0
- package/dist/provider-list-workflow.d.ts.map +1 -0
- package/dist/provider-list-workflow.js +95 -0
- package/dist/provider-wire-record.d.ts +3 -0
- package/dist/provider-wire-record.d.ts.map +1 -0
- package/dist/provider-wire-record.js +4 -0
- package/dist/providers-cli.d.ts.map +1 -1
- package/dist/providers-cli.js +5 -15
- package/dist/publish-merge-job.d.ts +68 -0
- package/dist/publish-merge-job.d.ts.map +1 -0
- package/dist/publish-merge-job.js +320 -0
- package/dist/publish-merge-timing.d.ts +18 -0
- package/dist/publish-merge-timing.d.ts.map +1 -0
- package/dist/publish-merge-timing.js +23 -0
- package/dist/task-export-workflow.d.ts +4 -0
- package/dist/task-export-workflow.d.ts.map +1 -0
- package/dist/task-export-workflow.js +46 -0
- package/dist/workbench-cli.d.ts +4 -0
- package/dist/workbench-cli.d.ts.map +1 -1
- package/dist/workbench-cli.js +11 -1
- package/dist/workspace-bootstrap-job.d.ts +1 -0
- package/dist/workspace-bootstrap-job.d.ts.map +1 -1
- package/dist/workspace-bootstrap-job.js +1 -1
- package/package.json +5 -2
- package/src/app-commands.ts +234 -66
- package/src/app-publish-failure.ts +7 -0
- package/src/app-publish-paths.ts +27 -0
- package/src/app-publish-workspace.ts +207 -0
- package/src/artifacts-git-runtime.ts +73 -31
- package/src/artifacts-session-merge.ts +253 -0
- package/src/dataset-append-workflow.ts +205 -0
- package/src/dataset-commands.ts +101 -261
- package/src/dataset-delete-workflow.ts +72 -0
- package/src/dataset-lock-workflow.ts +74 -0
- package/src/dataset-readme-workflow.ts +80 -0
- package/src/dataset-row-workflow.ts +248 -0
- package/src/dataset-split-reads.ts +43 -0
- package/src/dataset-transfer-download.ts +5 -5
- package/src/dataset-transfer-upload.ts +7 -7
- package/src/git-credential.ts +8 -1
- package/src/help.ts +32 -6
- package/src/hosted-boot.ts +72 -2
- package/src/hosted-harness-opencode.ts +67 -65
- package/src/hosted-loop-lifecycle.ts +4 -10
- package/src/hosted-loop.ts +6 -4
- package/src/hosted-model-cache.d.mts +2 -0
- package/src/hosted-model-cache.mjs +53 -0
- package/src/hosted-session-cli.ts +6 -1
- package/src/hosted-session-seed.ts +78 -0
- package/src/index.ts +10 -0
- package/src/instruction-delivery.ts +123 -0
- package/src/instruction-set-sync/index.ts +61 -14
- package/src/instruction-set-update/index.ts +4 -3
- package/src/instruction-sets-cli.ts +19 -27
- package/src/json-response.ts +8 -0
- package/src/jsonl-stream.ts +8 -0
- package/src/preview-runtime.ts +40 -10
- package/src/provider-list-workflow.ts +108 -0
- package/src/provider-wire-record.ts +4 -0
- package/src/providers-cli.ts +5 -13
- package/src/publish-merge-job.ts +350 -0
- package/src/publish-merge-timing.ts +27 -0
- package/src/task-export-workflow.ts +56 -0
- package/src/workbench-cli.ts +15 -1
- package/src/workspace-bootstrap-job.ts +1 -1
- package/vendor/skills/orizu/flows/onboard.md +1 -1
- package/vendor/skills/orizu/references/authority-map.md +2 -2
- package/vendor/skills/orizu/references/building-apps.md +24 -0
- package/vendor/skills/orizu/references/cli-reference.md +47 -4
- package/vendor/skills/orizu/references/dataset-design.md +1 -1
- package/vendor/skills/orizu/references/optimization-reports.md +1 -1
- package/vendor/skills/orizu/references/primer.md +1 -0
- package/vendor/skills/orizu/references/prompt-control-plane.md +9 -5
- package/dist/dataset-edit-rows.d.ts +0 -10
- package/dist/dataset-edit-rows.d.ts.map +0 -1
- package/dist/dataset-edit-rows.js +0 -90
- package/src/dataset-edit-rows.ts +0 -124
package/README.md
CHANGED
|
@@ -19,7 +19,7 @@ Note: the one task we do _not_ let you perform from your CLI is any reviews assi
|
|
|
19
19
|
|
|
20
20
|
## Requirements
|
|
21
21
|
|
|
22
|
-
- [Node.js
|
|
22
|
+
- [Node.js 22+](https://nodejs.org/en/download)
|
|
23
23
|
- Access to an Orizu web app/API
|
|
24
24
|
- A valid Orizu account
|
|
25
25
|
|
|
@@ -195,8 +195,8 @@ Agents are first-class users of this CLI: **every command supports `--json`**
|
|
|
195
195
|
(as a prefix, `orizu --json teams list`, or a trailing flag) and emits a single
|
|
196
196
|
machine-readable JSON document instead of formatted text. Discover the full
|
|
197
197
|
command surface, including global options, with `orizu capabilities --json`.
|
|
198
|
-
Hosted agents may read and sync instruction sets, create profile seeds, run shape add/remove with team-scoped curator authority, and prepare complete manifests. A local coding agent using the user's token runs instruction create, push, shape add/remove, archive, and restore itself after plan ratification. It gathers only read-only pointer-resolution and binding evidence; a human curator executes every production/default pointer command on every surface.
|
|
199
|
-
In a hosted session, a human curator using the local CLI must run create/push, archive/restore, and every pointer command; shape add/remove stays agent-runnable because it creates unpromoted heads only.
|
|
198
|
+
Hosted agents may read and sync instruction sets, create profile seeds, run shape add/remove before first promotion with team-scoped curator authority, and prepare complete manifests. A local coding agent using the user's token runs instruction create, push, shape add/remove, archive, and restore itself after plan ratification. It gathers only read-only pointer-resolution and binding evidence; a human curator executes every production/default pointer command on every surface.
|
|
199
|
+
In a hosted session, a human curator using the local CLI must run create/push, archive/restore, and every pointer command; shape add/remove stays agent-runnable before first promotion because it creates unpromoted heads only; sets that existed when the freeze shipped are already frozen. The first promotion of any profile permanently freezes component names; a changed published shape requires a new instruction set, even after archiving or removing production pointers.
|
|
200
200
|
|
|
201
201
|
## Authentication
|
|
202
202
|
|
|
@@ -336,6 +336,10 @@ orizu logout
|
|
|
336
336
|
<td>Download a dataset</td>
|
|
337
337
|
<td><code>orizu datasets download --dataset <datasetId> --format jsonl --out ./dataset.jsonl</code></td>
|
|
338
338
|
</tr>
|
|
339
|
+
<tr>
|
|
340
|
+
<td>Inspect saved splits and download validation rows</td>
|
|
341
|
+
<td><code>orizu datasets splits list <datasetVersionId> --json</code><br><code>orizu datasets splits show <splitSetId> --json</code><br><code>orizu datasets download --dataset-version <datasetVersionId> --split-set <splitSetId> --split validation --format jsonl --out ./validation.jsonl</code></td>
|
|
342
|
+
</tr>
|
|
339
343
|
<tr>
|
|
340
344
|
<td>Append dataset rows</td>
|
|
341
345
|
<td><code>orizu datasets append --dataset <datasetId> --file ./datasets/support-extra.jsonl</code></td>
|
|
@@ -485,6 +489,52 @@ SIGINT/SIGTERM cancels a download. Upload writes
|
|
|
485
489
|
have no additional transient retries; the existing session refresh behavior is
|
|
486
490
|
unchanged.
|
|
487
491
|
|
|
492
|
+
Dataset `append` prints one result document with `--json`, including JSONL and
|
|
493
|
+
multiple chunks. Its failure document preserves the resolved `datasetId`,
|
|
494
|
+
`confirmedRows` and `confirmedChunks`, and identifies the acquired `failedChunk`
|
|
495
|
+
when one exists. A lost or malformed receipt leaves that chunk's outcome
|
|
496
|
+
`unknown`: inspect and reconcile the dataset before repeating the write.
|
|
497
|
+
Earlier acknowledged rows remain appended. Each admitted append request uses
|
|
498
|
+
the same two-minute transfer deadline and validated environment override,
|
|
499
|
+
including response-body consumption. This deadline does not time out file input
|
|
500
|
+
or interactive selection. SIGINT/SIGTERM closes append's owned JSONL reader and
|
|
501
|
+
in-flight transport; retained interactive selection keeps ordinary process signal
|
|
502
|
+
termination. Append adds no transient write retries or write deduplication.
|
|
503
|
+
|
|
504
|
+
Dataset `edit-rows` and `delete-rows` use the same transfer deadline for each
|
|
505
|
+
request, including its response body. When a request times out, loses its
|
|
506
|
+
connection or gets a server error or a malformed reply, the message says the
|
|
507
|
+
change may already be applied (or removed): check those rows before retrying.
|
|
508
|
+
A refusal from the server (for example, a locked dataset) leaves `edit-rows`
|
|
509
|
+
with the usual retry advice, and reports `delete-rows` as refused.
|
|
510
|
+
SIGINT/SIGTERM aborts the request in flight and exits 130/143. Neither command
|
|
511
|
+
retries a write automatically.
|
|
512
|
+
|
|
513
|
+
Dataset `lock` uses the same transfer deadline for its request, including the
|
|
514
|
+
response body. After a timeout, a lost connection, a server error or a malformed
|
|
515
|
+
reply, the message says the dataset may already be locked: running `lock` again
|
|
516
|
+
is safe and shows its current state. A refusal from the server keeps its usual
|
|
517
|
+
message. Lock keeps ordinary process signal termination and never retries.
|
|
518
|
+
|
|
519
|
+
Dataset `delete` asks you to type the dataset id first, then uses the same
|
|
520
|
+
transfer deadline for its request, including the response body. After a
|
|
521
|
+
timeout, a lost connection, a server error or a malformed reply, the message
|
|
522
|
+
says the dataset may already be deleted: check with
|
|
523
|
+
`orizu datasets list --status all` before retrying. When tasks or app versions
|
|
524
|
+
still use the dataset, the refusal also names `orizu datasets archive <id>`.
|
|
525
|
+
Delete keeps ordinary process signal termination and never retries.
|
|
526
|
+
|
|
527
|
+
Dataset `readme set` uses the same transfer deadline for its request, including
|
|
528
|
+
the response body. Each save adds a new README version. After a timeout, a lost
|
|
529
|
+
connection, a server error or a malformed reply, the message says the README may
|
|
530
|
+
already be saved as a new version: check the dataset's README tab before saving
|
|
531
|
+
again, since another save would add a second version. When another save for the
|
|
532
|
+
same dataset happened at the same time, the message says yours was not saved
|
|
533
|
+
and to run the command again. A README file that cannot be read is named and
|
|
534
|
+
nothing is sent. `readme set` keeps ordinary process signal termination and
|
|
535
|
+
never retries.
|
|
536
|
+
|
|
537
|
+
|
|
488
538
|
## Interactive And Automated Usage
|
|
489
539
|
|
|
490
540
|
Many commands can prompt for missing team, project, app, dataset, or task selections in an interactive terminal. In scripts and CI, pass explicit flags instead:
|
|
@@ -499,3 +549,45 @@ Use `--json` on supported task and app commands when automation needs structured
|
|
|
499
549
|
|
|
500
550
|
- [docs/cli.md](docs/cli.md): complete CLI guide and command reference
|
|
501
551
|
- [skills/orizu/references/cli-reference.md](skills/orizu/references/cli-reference.md): compact command matrix and end-to-end flows
|
|
552
|
+
|
|
553
|
+
If the server loses or cannot decode a database append acknowledgement, it preserves the request's prepared row artifacts because rows may already reference them. Unknown outcomes require inspection; automatic orphan reconciliation and write deduplication are not promised. Known SQL refusals clean up only that request's newly prepared artifacts.
|
|
554
|
+
|
|
555
|
+
### Enrich validation rows while preserving split assignments
|
|
556
|
+
|
|
557
|
+
Start with the immutable dataset version ID returned by dataset upload or version
|
|
558
|
+
creation. List its saved split sets, then inspect one set to find the exact
|
|
559
|
+
partition name (custom names and empty partitions are retained):
|
|
560
|
+
|
|
561
|
+
```bash
|
|
562
|
+
orizu datasets splits list DATASET_VERSION_ID --json
|
|
563
|
+
orizu datasets splits show SPLIT_SET_ID --json > split.json
|
|
564
|
+
orizu datasets download --dataset-version DATASET_VERSION_ID --split-set SPLIT_SET_ID --split validation --format jsonl --out validation.jsonl
|
|
565
|
+
```
|
|
566
|
+
|
|
567
|
+
`validation.jsonl` contains only that partition, in its saved order. Each row has
|
|
568
|
+
its canonical `id` and the fields stored in that version. These reads stay fixed
|
|
569
|
+
when the live dataset changes. No prompt, runner, scorer or optimization is needed.
|
|
570
|
+
|
|
571
|
+
The assignment JSON retains set and partition metadata, including arrays, scalars
|
|
572
|
+
and null values, together with exact saved memberships.
|
|
573
|
+
|
|
574
|
+
Enrich the exported rows in your own workflow, keeping every `id` unchanged.
|
|
575
|
+
Combine them with the other rows when preparing the complete enriched dataset.
|
|
576
|
+
After uploading that dataset or creating its version, use the new version's ID
|
|
577
|
+
explicitly to reuse every original assignment:
|
|
578
|
+
|
|
579
|
+
```bash
|
|
580
|
+
orizu datasets splits create TARGET_DATASET_VERSION_ID --from-file split.json --json
|
|
581
|
+
```
|
|
582
|
+
|
|
583
|
+
The import accepts the `name`, `strategy`, `seed`, `metadata` and
|
|
584
|
+
`partitions: [{name, row_ids}]` from show JSON. Source identity is for inspection;
|
|
585
|
+
the command's target version decides where assignments are created. Every
|
|
586
|
+
referenced canonical row ID must exist in that target. Missing IDs fail instead
|
|
587
|
+
of being dropped or remapped. Unknown or inaccessible versions, sets or names,
|
|
588
|
+
mismatched selectors and incomplete artifacts fail; pinned reads never fall back
|
|
589
|
+
to live data. Existing live downloads remain available with `--dataset`.
|
|
590
|
+
|
|
591
|
+
For saved split names beginning with `--`, use the unambiguous equals spelling:
|
|
592
|
+
`orizu datasets download --dataset-version DATASET_VERSION_ID --split-set SPLIT_SET_ID --split=--validation --format jsonl --out validation.jsonl`.
|
|
593
|
+
The same spelling supports `--split=--json` and `--split=--help`; all pinned selectors remain required.
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"app-commands.d.ts","sourceRoot":"","sources":["../src/app-commands.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"app-commands.d.ts","sourceRoot":"","sources":["../src/app-commands.ts"],"names":[],"mappings":"AAuCA,iBAAe,QAAQ,kBActB;AAED,iBAAS,cAAc,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM,CAU/C;AAED,iBAAS,eAAe,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM,CAUhD;AAED,iBAAS,YAAY,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAE9D;AAeD,iBAAS,QAAQ,CAAC,KAAK,EAAE,OAAO,GAAG,KAAK,IAAI,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAElE;AAED,iBAAS,gBAAgB,CAAC,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAAE,GAAG,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS,CAG1F;AAED,iBAAS,gBAAgB,CAAC,KAAK,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,MAAM,CAUjE;AAED,iBAAS,SAAS,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,GAAG,MAAM,CAEjD;AAED,iBAAS,qBAAqB,CAAC,QAAQ,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAAE,SAAS,EAAE,MAAM,GAAG;IACpF,IAAI,EAAE,MAAM,CAAA;IACZ,QAAQ,EAAE,MAAM,CAAA;IAChB,IAAI,EAAE,MAAM,CAAA;CACb,CAeA;AAED,iBAAS,kBAAkB,CAAC,QAAQ,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAAE,SAAS,EAAE,MAAM;;;;;IAoB/E;AAED,iBAAS,wBAAwB,CAAC,OAAO,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,QAGjE;AAED,iBAAS,gBAAgB,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAEjE;AAyED,iBAAe,iBAAiB,kBAmG/B;AAED,iBAAe,kBAAkB,kBAiDhC;AAED,iBAAe,iBAAiB,kBAwF/B;AAED,iBAAe,cAAc,kBAgD5B;AA+CD,iBAAe,SAAS,kBA2CvB;AAED,yFAAyF;AACzF,wBAAgB,oBAAoB,CAAC,UAAU,EAAE,MAAM,GAAG,IAAI,GAAG,SAAS,EAAE,eAAe,EAAE,MAAM,GAAG,MAAM,CAK3G;AAED,iBAAe,eAAe,kBAmD7B;AAED,OAAO,EACL,cAAc,EACd,YAAY,EACZ,gBAAgB,EAChB,qBAAqB,EACrB,kBAAkB,EAClB,gBAAgB,EAChB,QAAQ,EACR,gBAAgB,EAChB,wBAAwB,EACxB,SAAS,EACT,eAAe,EACf,QAAQ,EACR,iBAAiB,EACjB,kBAAkB,EAClB,iBAAiB,EACjB,cAAc,EACd,SAAS,EACT,eAAe,GAChB,CAAA"}
|
package/dist/app-commands.js
CHANGED
|
@@ -1,16 +1,20 @@
|
|
|
1
1
|
// ORI-2044: moved from index.ts to keep app commands together.
|
|
2
2
|
import { readFileSync, statSync, mkdirSync, writeFileSync, realpathSync, } from 'fs';
|
|
3
3
|
import { normalize, isAbsolute, join, dirname, } from 'path';
|
|
4
|
-
import { createHash } from 'crypto';
|
|
4
|
+
import { createHash, randomUUID } from 'crypto';
|
|
5
5
|
import { getArg, getArchiveListStatus, hasJsonFlag, expandHomePath, hasArg, } from './command-line-arguments.js';
|
|
6
6
|
import { resolveProjectSlug, fetchApps, selectAppIdInteractively } from './account-directory.js';
|
|
7
7
|
import { printJson, printLine, getErrorMessage } from './cli-console-output.js';
|
|
8
8
|
import { printAppSummaries } from './archive-artifacts-cli.js';
|
|
9
9
|
import { isNodeError, formatTerminalLink } from './auth-commands.js';
|
|
10
|
+
import { parseCliProjectSlug } from './cli-project-slug.js';
|
|
11
|
+
import { AppPublishFailure } from './app-publish-failure.js';
|
|
12
|
+
import { inspectAppDestination } from './app-publish-paths.js';
|
|
10
13
|
import { authedFetch, getBaseUrl } from './http.js';
|
|
11
14
|
import { appPageUrl } from './app-page-url.js';
|
|
12
15
|
import { parseJsonResponse, sanitizeHumanInlineText, sanitizeTerminalText } from './json-response.js';
|
|
13
16
|
import { runLocalAppPreview } from './preview-runtime.js';
|
|
17
|
+
import { findWorkspaceRoot } from './workspace.js';
|
|
14
18
|
async function listApps() {
|
|
15
19
|
const project = getArg('--project') || await resolveProjectSlug(null);
|
|
16
20
|
const baseUrl = getBaseUrl();
|
|
@@ -51,7 +55,9 @@ function readSourceBytes(pathArg) {
|
|
|
51
55
|
}
|
|
52
56
|
}
|
|
53
57
|
function readJsonFile(pathArg) {
|
|
54
|
-
|
|
58
|
+
return parseJsonFileContents(readSourceFile(pathArg), pathArg);
|
|
59
|
+
}
|
|
60
|
+
function parseJsonFileContents(raw, pathArg) {
|
|
55
61
|
try {
|
|
56
62
|
const parsed = JSON.parse(raw);
|
|
57
63
|
if (!parsed || typeof parsed !== 'object' || Array.isArray(parsed)) {
|
|
@@ -127,47 +133,160 @@ function writeTextFileEnsuringDir(pathArg, content) {
|
|
|
127
133
|
function readManifestFile(dirArg) {
|
|
128
134
|
return readJsonFile(join(expandHomePath(dirArg), 'manifest.json'));
|
|
129
135
|
}
|
|
136
|
+
const LOCAL_PUBLISH_NOTE = 'Note: this app version is not in the team repository yet; it reaches git when published from a hosted session.';
|
|
137
|
+
const APP_ID_PATTERN = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/;
|
|
138
|
+
/** The workspace root when this runs in a hosted session, else null. */
|
|
139
|
+
function hostedWorkspaceRoot() {
|
|
140
|
+
if (!process.env.ORIZU_SESSION_ID?.trim())
|
|
141
|
+
return null;
|
|
142
|
+
const workspaceRoot = findWorkspaceRoot(process.cwd());
|
|
143
|
+
if (!workspaceRoot)
|
|
144
|
+
throw new Error('Hosted app publishing must run inside the attached workspace. Run this command from the workspace containing orizu.team.json.');
|
|
145
|
+
return workspaceRoot;
|
|
146
|
+
}
|
|
147
|
+
/** The hosted publish path, loaded only when it runs: it needs Effect, which
|
|
148
|
+
* the rest of the CLI does not load at startup. */
|
|
149
|
+
function loadAppPublishWorkspace() {
|
|
150
|
+
return import('./app-publish-workspace.js');
|
|
151
|
+
}
|
|
152
|
+
/** The app as committed into its folder: the files exactly as the agent wrote them. */
|
|
153
|
+
function appFilesFromArgs(filePath, inputSchemaPath, outputSchemaPath) {
|
|
154
|
+
return { sourceCode: readSourceFile(filePath), inputSchema: readSourceFile(inputSchemaPath), outputSchema: readSourceFile(outputSchemaPath) };
|
|
155
|
+
}
|
|
156
|
+
/** ORI-2280: a hosted publish the merge stopped. The server's text says what to
|
|
157
|
+
* do; a create's rerun must name the same app id, so its folder is reused. A
|
|
158
|
+
* conflict also adds the team copy remote the text tells the agent to pull. */
|
|
159
|
+
async function publishRefusalError(responseText, workspaceRoot) {
|
|
160
|
+
let body;
|
|
161
|
+
try {
|
|
162
|
+
body = JSON.parse(responseText);
|
|
163
|
+
}
|
|
164
|
+
catch {
|
|
165
|
+
return null;
|
|
166
|
+
}
|
|
167
|
+
if (!isRecord(body) || typeof body.error !== 'string' || typeof body.code !== 'string' || !body.code.startsWith('publish_'))
|
|
168
|
+
return null;
|
|
169
|
+
let message = sanitizeTerminalText(body.error);
|
|
170
|
+
if (body.code === 'publish_conflict') {
|
|
171
|
+
const { addTeamCopyRemote } = await loadAppPublishWorkspace();
|
|
172
|
+
const remoteNote = await addTeamCopyRemote(workspaceRoot);
|
|
173
|
+
if (remoteNote)
|
|
174
|
+
message = `${message} ${remoteNote}`;
|
|
175
|
+
}
|
|
176
|
+
return new Error(message);
|
|
177
|
+
}
|
|
178
|
+
function printPublishedCommit(commit, isHosted) {
|
|
179
|
+
if (commit) {
|
|
180
|
+
const where = commit.outcome === 'merged' ? 'Merged into' : 'Already in';
|
|
181
|
+
printLine(`${where} the team copy: ${sanitizeTerminalText(commit.sha.slice(0, 7))}`);
|
|
182
|
+
}
|
|
183
|
+
else if (!isHosted) {
|
|
184
|
+
printLine(LOCAL_PUBLISH_NOTE);
|
|
185
|
+
}
|
|
186
|
+
}
|
|
187
|
+
/** Quote each original argument so spaces and quotes survive a copied retry. */
|
|
188
|
+
function shellSingleQuote(value) {
|
|
189
|
+
return `'${value.replace(/'/g, "'\\''")}'`;
|
|
190
|
+
}
|
|
191
|
+
function canonicalRetryInputPath(workspaceRoot, folder, filename, originalPath) {
|
|
192
|
+
const canonicalPath = join(workspaceRoot, folder, filename);
|
|
193
|
+
try {
|
|
194
|
+
return inspectAppDestination(workspaceRoot, join(folder, filename)) ? canonicalPath : originalPath;
|
|
195
|
+
}
|
|
196
|
+
catch {
|
|
197
|
+
return originalPath;
|
|
198
|
+
}
|
|
199
|
+
}
|
|
130
200
|
async function createAppFromFile() {
|
|
131
|
-
const
|
|
201
|
+
const workspaceRoot = hostedWorkspaceRoot();
|
|
202
|
+
let project = getArg('--project');
|
|
132
203
|
const name = getArg('--name');
|
|
133
204
|
const datasetId = getArg('--dataset');
|
|
134
205
|
const filePath = getArg('--file');
|
|
135
206
|
const inputSchemaPath = getArg('--input-schema');
|
|
136
207
|
const outputSchemaPath = getArg('--output-schema');
|
|
137
208
|
const component = getArg('--component') || undefined;
|
|
209
|
+
const requestedAppId = getArg('--id') ?? undefined;
|
|
138
210
|
if (!project || !name || !datasetId || !filePath || !inputSchemaPath || !outputSchemaPath) {
|
|
139
|
-
throw new Error('Usage: orizu apps create --project <team/project> --name <name> --dataset <datasetId> --file <path> --input-schema <json-path> --output-schema <json-path> [--component <name>]');
|
|
211
|
+
throw new Error('Usage: orizu apps create --project <team/project> --name <name> --dataset <datasetId> --file <path> --input-schema <json-path> --output-schema <json-path> [--component <name>] [--id <app-id>]');
|
|
140
212
|
}
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
const outputJsonSchema = readJsonFile(outputSchemaPath);
|
|
144
|
-
const response = await authedFetch('/api/cli/apps/create-from-file', {
|
|
145
|
-
method: 'POST',
|
|
146
|
-
headers: { 'Content-Type': 'application/json' },
|
|
147
|
-
body: JSON.stringify({
|
|
148
|
-
projectSlug: project,
|
|
149
|
-
name,
|
|
150
|
-
datasetId,
|
|
151
|
-
sourceCode,
|
|
152
|
-
componentName: component,
|
|
153
|
-
inputJsonSchema,
|
|
154
|
-
outputJsonSchema,
|
|
155
|
-
}),
|
|
156
|
-
});
|
|
157
|
-
if (!response.ok) {
|
|
158
|
-
throw new Error(`Failed to create app: ${await response.text()}`);
|
|
213
|
+
if (requestedAppId !== undefined && !APP_ID_PATTERN.test(requestedAppId)) {
|
|
214
|
+
throw new Error('--id must be a lowercase app id (UUID), as printed by the earlier publish');
|
|
159
215
|
}
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
216
|
+
if (workspaceRoot) {
|
|
217
|
+
const parsedProject = parseCliProjectSlug(project);
|
|
218
|
+
const slug = /^[a-z0-9][a-z0-9-]{0,99}$/;
|
|
219
|
+
if (!parsedProject || !slug.test(parsedProject.teamSlug) || !slug.test(parsedProject.projectSlug)) {
|
|
220
|
+
throw new Error('--project must be a valid <team/project> reference');
|
|
221
|
+
}
|
|
222
|
+
project = `${parsedProject.teamSlug}/${parsedProject.projectSlug}`;
|
|
223
|
+
}
|
|
224
|
+
const files = appFilesFromArgs(filePath, inputSchemaPath, outputSchemaPath);
|
|
225
|
+
const sourceCode = files.sourceCode;
|
|
226
|
+
const inputJsonSchema = parseJsonFileContents(files.inputSchema, inputSchemaPath);
|
|
227
|
+
const outputJsonSchema = parseJsonFileContents(files.outputSchema, outputSchemaPath);
|
|
228
|
+
// In a hosted session the app is committed into its folder and pushed first;
|
|
229
|
+
// the server merges that commit into the team copy before recording the app.
|
|
230
|
+
let appId = requestedAppId;
|
|
231
|
+
let sessionCommitSha;
|
|
232
|
+
let recoveryFolder;
|
|
233
|
+
let filesMaterialized = false;
|
|
234
|
+
try {
|
|
235
|
+
if (workspaceRoot) {
|
|
236
|
+
const projectSlug = parseCliProjectSlug(project).projectSlug;
|
|
237
|
+
appId ??= randomUUID();
|
|
238
|
+
recoveryFolder = `projects/${projectSlug}/apps/${appId}`;
|
|
239
|
+
const { pushAppToSessionCopy } = await loadAppPublishWorkspace();
|
|
240
|
+
sessionCommitSha = await pushAppToSessionCopy(workspaceRoot, {
|
|
241
|
+
projectSlug,
|
|
242
|
+
appId,
|
|
243
|
+
files,
|
|
244
|
+
});
|
|
245
|
+
filesMaterialized = true;
|
|
246
|
+
}
|
|
247
|
+
const response = await authedFetch('/api/cli/apps/create-from-file', {
|
|
248
|
+
method: 'POST',
|
|
249
|
+
headers: { 'Content-Type': 'application/json' },
|
|
250
|
+
body: JSON.stringify({
|
|
251
|
+
projectSlug: project,
|
|
252
|
+
name,
|
|
253
|
+
datasetId,
|
|
254
|
+
sourceCode,
|
|
255
|
+
componentName: component,
|
|
256
|
+
inputJsonSchema,
|
|
257
|
+
outputJsonSchema,
|
|
258
|
+
...(appId !== undefined ? { appId } : {}),
|
|
259
|
+
...(sessionCommitSha !== undefined ? { sessionCommitSha } : {}),
|
|
260
|
+
}),
|
|
261
|
+
});
|
|
262
|
+
if (!response.ok) {
|
|
263
|
+
const text = await response.text();
|
|
264
|
+
const refusal = workspaceRoot ? await publishRefusalError(text, workspaceRoot) : null;
|
|
265
|
+
throw refusal ?? new Error(`Failed to create app: ${text}`);
|
|
266
|
+
}
|
|
267
|
+
const data = await parseJsonResponse(response, 'App create');
|
|
268
|
+
if (hasJsonFlag()) {
|
|
269
|
+
printJson({ app: { ...data.app, pageUrl: data.app.url || appPageUrl(getBaseUrl(), data.app.id) }, warnings: data.warnings || [] });
|
|
270
|
+
return;
|
|
271
|
+
}
|
|
272
|
+
printLine(`Created app ${sanitizeTerminalText(data.app.name)} (${sanitizeTerminalText(data.app.id)}) v${data.app.versionNum}`);
|
|
273
|
+
if (data.app.url) {
|
|
274
|
+
printLine(`View app: ${formatTerminalLink(data.app.url)}`);
|
|
275
|
+
}
|
|
276
|
+
printPublishedCommit(data.app.publishedCommit, workspaceRoot !== null);
|
|
277
|
+
if (data.warnings?.length) {
|
|
278
|
+
printLine(`Warnings: ${sanitizeTerminalText(data.warnings.join('; '))}`);
|
|
279
|
+
}
|
|
168
280
|
}
|
|
169
|
-
|
|
170
|
-
|
|
281
|
+
catch (error) {
|
|
282
|
+
if (!workspaceRoot || !appId || !recoveryFolder)
|
|
283
|
+
throw error;
|
|
284
|
+
const useCanonicalInputs = filesMaterialized || (error instanceof AppPublishFailure && error.filesMaterialized);
|
|
285
|
+
const retryArgs = ['orizu', '--server', getBaseUrl(), 'apps', 'create', '--project', project, '--name', name, '--dataset', datasetId,
|
|
286
|
+
'--file', useCanonicalInputs ? canonicalRetryInputPath(workspaceRoot, recoveryFolder, 'App.tsx', filePath) : filePath, '--input-schema', useCanonicalInputs ? canonicalRetryInputPath(workspaceRoot, recoveryFolder, 'input.schema.json', inputSchemaPath) : inputSchemaPath,
|
|
287
|
+
'--output-schema', useCanonicalInputs ? canonicalRetryInputPath(workspaceRoot, recoveryFolder, 'output.schema.json', outputSchemaPath) : outputSchemaPath,
|
|
288
|
+
...(component ? ['--component', component] : []), ...(hasJsonFlag() ? ['--json'] : []), '--id', appId];
|
|
289
|
+
throw new Error(`${getErrorMessage(error)}\nApp ID: ${appId}\nFolder: ${recoveryFolder}\nRetry: ${retryArgs.map(shellSingleQuote).join(' ')}`);
|
|
171
290
|
}
|
|
172
291
|
}
|
|
173
292
|
async function previewAppFromFile() {
|
|
@@ -217,6 +336,7 @@ async function previewAppFromFile() {
|
|
|
217
336
|
}
|
|
218
337
|
}
|
|
219
338
|
async function updateAppFromFile() {
|
|
339
|
+
const workspaceRoot = hostedWorkspaceRoot();
|
|
220
340
|
const filePath = getArg('--file');
|
|
221
341
|
const inputSchemaPath = getArg('--input-schema');
|
|
222
342
|
const outputSchemaPath = getArg('--output-schema');
|
|
@@ -230,32 +350,70 @@ async function updateAppFromFile() {
|
|
|
230
350
|
const selected = await selectAppIdInteractively(project);
|
|
231
351
|
appId = selected.appId;
|
|
232
352
|
}
|
|
233
|
-
const
|
|
234
|
-
const
|
|
235
|
-
const
|
|
236
|
-
const
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
353
|
+
const files = appFilesFromArgs(filePath, inputSchemaPath, outputSchemaPath);
|
|
354
|
+
const sourceCode = files.sourceCode;
|
|
355
|
+
const inputJsonSchema = parseJsonFileContents(files.inputSchema, inputSchemaPath);
|
|
356
|
+
const outputJsonSchema = parseJsonFileContents(files.outputSchema, outputSchemaPath);
|
|
357
|
+
// In a hosted session the app is committed into its folder and pushed first;
|
|
358
|
+
// the server merges that commit into the team copy before recording the version.
|
|
359
|
+
let recoveryFolder;
|
|
360
|
+
let filesMaterialized = false;
|
|
361
|
+
try {
|
|
362
|
+
let sessionCommitSha;
|
|
363
|
+
if (workspaceRoot) {
|
|
364
|
+
const folderResponse = await authedFetch(`/api/cli/apps/${encodeURIComponent(appId)}`);
|
|
365
|
+
if (!folderResponse.ok) {
|
|
366
|
+
throw new Error(`Failed to find the app's project: ${await folderResponse.text()}`);
|
|
367
|
+
}
|
|
368
|
+
const folder = await parseJsonResponse(folderResponse, 'App folder');
|
|
369
|
+
recoveryFolder = `projects/${folder.projectSlug}/apps/${folder.appId}`;
|
|
370
|
+
const { pushAppToSessionCopy } = await loadAppPublishWorkspace();
|
|
371
|
+
sessionCommitSha = await pushAppToSessionCopy(workspaceRoot, {
|
|
372
|
+
projectSlug: folder.projectSlug,
|
|
373
|
+
appId: folder.appId,
|
|
374
|
+
files,
|
|
375
|
+
});
|
|
376
|
+
filesMaterialized = true;
|
|
377
|
+
}
|
|
378
|
+
const response = await authedFetch(`/api/cli/apps/${encodeURIComponent(appId)}/update-from-file`, {
|
|
379
|
+
method: 'POST',
|
|
380
|
+
headers: { 'Content-Type': 'application/json' },
|
|
381
|
+
body: JSON.stringify({
|
|
382
|
+
sourceCode,
|
|
383
|
+
componentName: component,
|
|
384
|
+
inputJsonSchema,
|
|
385
|
+
outputJsonSchema,
|
|
386
|
+
...(sessionCommitSha !== undefined ? { sessionCommitSha } : {}),
|
|
387
|
+
}),
|
|
388
|
+
});
|
|
389
|
+
if (!response.ok) {
|
|
390
|
+
const text = await response.text();
|
|
391
|
+
const refusal = workspaceRoot ? await publishRefusalError(text, workspaceRoot) : null;
|
|
392
|
+
throw refusal ?? new Error(`Failed to update app: ${text}`);
|
|
393
|
+
}
|
|
394
|
+
const data = await parseJsonResponse(response, 'App update');
|
|
395
|
+
const pageUrl = appPageUrl(getBaseUrl(), data.app.id);
|
|
396
|
+
if (hasJsonFlag()) {
|
|
397
|
+
printJson({ app: { ...data.app, pageUrl }, warnings: data.warnings || [] });
|
|
398
|
+
return;
|
|
399
|
+
}
|
|
400
|
+
printLine(`Updated app ${sanitizeTerminalText(data.app.name)} (${sanitizeTerminalText(data.app.id)}) to v${data.app.versionNum}`);
|
|
401
|
+
printLine(`View app: ${formatTerminalLink(pageUrl)}`);
|
|
402
|
+
printPublishedCommit(data.app.publishedCommit, workspaceRoot !== null);
|
|
403
|
+
if (data.warnings?.length) {
|
|
404
|
+
printLine(`Warnings: ${sanitizeTerminalText(data.warnings.join('; '))}`);
|
|
405
|
+
}
|
|
254
406
|
}
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
407
|
+
catch (error) {
|
|
408
|
+
if (!workspaceRoot || !recoveryFolder)
|
|
409
|
+
throw error;
|
|
410
|
+
const useCanonicalInputs = filesMaterialized || (error instanceof AppPublishFailure && error.filesMaterialized);
|
|
411
|
+
const retryArgs = ['orizu', '--server', getBaseUrl(), 'apps', 'update', '--app', appId,
|
|
412
|
+
'--file', useCanonicalInputs ? canonicalRetryInputPath(workspaceRoot, recoveryFolder, 'App.tsx', filePath) : filePath,
|
|
413
|
+
'--input-schema', useCanonicalInputs ? canonicalRetryInputPath(workspaceRoot, recoveryFolder, 'input.schema.json', inputSchemaPath) : inputSchemaPath,
|
|
414
|
+
'--output-schema', useCanonicalInputs ? canonicalRetryInputPath(workspaceRoot, recoveryFolder, 'output.schema.json', outputSchemaPath) : outputSchemaPath,
|
|
415
|
+
...(component ? ['--component', component] : []), ...(hasJsonFlag() ? ['--json'] : [])];
|
|
416
|
+
throw new Error(`${getErrorMessage(error)}\nApp ID: ${appId}\nFolder: ${recoveryFolder}\nRetry: ${retryArgs.map(shellSingleQuote).join(' ')}`);
|
|
259
417
|
}
|
|
260
418
|
}
|
|
261
419
|
async function linkAppDataset() {
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
/** Recovery may use canonical inputs only after this attempt wrote its full snapshot. */
|
|
2
|
+
export declare class AppPublishFailure extends Error {
|
|
3
|
+
readonly filesMaterialized: boolean;
|
|
4
|
+
constructor(message: string, filesMaterialized: boolean);
|
|
5
|
+
}
|
|
6
|
+
//# sourceMappingURL=app-publish-failure.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"app-publish-failure.d.ts","sourceRoot":"","sources":["../src/app-publish-failure.ts"],"names":[],"mappings":"AAAA,yFAAyF;AACzF,qBAAa,iBAAkB,SAAQ,KAAK;IACb,QAAQ,CAAC,iBAAiB,EAAE,OAAO;gBAApD,OAAO,EAAE,MAAM,EAAW,iBAAiB,EAAE,OAAO;CAIjE"}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
/** Recovery may use canonical inputs only after this attempt wrote its full snapshot. */
|
|
2
|
+
export class AppPublishFailure extends Error {
|
|
3
|
+
filesMaterialized;
|
|
4
|
+
constructor(message, filesMaterialized) {
|
|
5
|
+
super(message);
|
|
6
|
+
this.filesMaterialized = filesMaterialized;
|
|
7
|
+
this.name = 'AppPublishFailure';
|
|
8
|
+
}
|
|
9
|
+
}
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
/** Inspect canonical destinations without following aliases. All callers check
|
|
2
|
+
* the whole set before materializing it; this does not claim race-proof access. */
|
|
3
|
+
export declare function inspectAppDestination(root: string, path: string): boolean;
|
|
4
|
+
//# sourceMappingURL=app-publish-paths.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"app-publish-paths.d.ts","sourceRoot":"","sources":["../src/app-publish-paths.ts"],"names":[],"mappings":"AAGA;mFACmF;AACnF,wBAAgB,qBAAqB,CAAC,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,OAAO,CAqBzE"}
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
import { lstatSync } from 'node:fs';
|
|
2
|
+
import { isAbsolute, relative, resolve, sep } from 'node:path';
|
|
3
|
+
/** Inspect canonical destinations without following aliases. All callers check
|
|
4
|
+
* the whole set before materializing it; this does not claim race-proof access. */
|
|
5
|
+
export function inspectAppDestination(root, path) {
|
|
6
|
+
const base = resolve(root);
|
|
7
|
+
const destination = resolve(base, path);
|
|
8
|
+
const tail = relative(base, destination);
|
|
9
|
+
if (!tail || tail === '..' || tail.startsWith(`..${sep}`) || isAbsolute(tail))
|
|
10
|
+
throw new Error('App destination is outside the workspace');
|
|
11
|
+
const rootStat = lstatSync(base);
|
|
12
|
+
if (rootStat.isSymbolicLink() || !rootStat.isDirectory())
|
|
13
|
+
throw new Error('App workspace must be an ordinary directory');
|
|
14
|
+
const segments = tail.split(sep);
|
|
15
|
+
let current = base;
|
|
16
|
+
for (const [index, segment] of segments.entries()) {
|
|
17
|
+
current = resolve(current, segment);
|
|
18
|
+
const stat = lstatSync(current, { throwIfNoEntry: false });
|
|
19
|
+
if (!stat)
|
|
20
|
+
return false;
|
|
21
|
+
if (stat.isSymbolicLink())
|
|
22
|
+
throw new Error('App destination must not contain symbolic links');
|
|
23
|
+
if (index < segments.length - 1) {
|
|
24
|
+
if (!stat.isDirectory())
|
|
25
|
+
throw new Error('App destination parent must be an ordinary directory');
|
|
26
|
+
}
|
|
27
|
+
else if (!stat.isFile() || stat.nlink > 1) {
|
|
28
|
+
throw new Error('App destination must be an ordinary file without hardlink aliases');
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
return true;
|
|
32
|
+
}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
export interface AppFiles {
|
|
2
|
+
readonly sourceCode: string;
|
|
3
|
+
readonly inputSchema: string;
|
|
4
|
+
readonly outputSchema: string;
|
|
5
|
+
}
|
|
6
|
+
/** Commits and pushes the app, answering the commit to publish. Throws the
|
|
7
|
+
* message the agent should act on. */
|
|
8
|
+
export declare function pushAppToSessionCopy(root: string, input: {
|
|
9
|
+
projectSlug: string;
|
|
10
|
+
appId: string;
|
|
11
|
+
files: AppFiles;
|
|
12
|
+
}): Promise<string>;
|
|
13
|
+
/** Adds the team copy remote; answers a sentence to add to the conflict
|
|
14
|
+
* message when it could not, else null. */
|
|
15
|
+
export declare function addTeamCopyRemote(root: string): Promise<string | null>;
|
|
16
|
+
//# sourceMappingURL=app-publish-workspace.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"app-publish-workspace.d.ts","sourceRoot":"","sources":["../src/app-publish-workspace.ts"],"names":[],"mappings":"AAgCA,MAAM,WAAW,QAAQ;IACvB,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAA;IAC3B,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAA;IAC5B,QAAQ,CAAC,YAAY,EAAE,MAAM,CAAA;CAC9B;AA+GD;sCACsC;AACtC,wBAAsB,oBAAoB,CAAC,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE;IAAE,WAAW,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,QAAQ,CAAA;CAAE,GAAG,OAAO,CAAC,MAAM,CAAC,CAcxI;AAgCD;2CAC2C;AAC3C,wBAAgB,iBAAiB,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,CAStE"}
|