octwin-cli 0.8.15 → 0.8.17
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/CHANGELOG.md +1109 -1017
- package/README.md +37 -29
- package/dist/cli.js +989 -467
- package/dist/lib/base.js +85 -0
- package/dist/lib/init-id.js +13 -0
- package/dist/lib/journey-check.js +119 -0
- package/dist/lib/kb-index.js +142 -18
- package/dist/lib/recipe.js +190 -0
- package/dist/lib/refusal.js +56 -0
- package/dist/lib/rename.js +1 -1
- package/package.json +46 -46
- package/templates/starter/commands.yaml +11 -12
- package/templates/starter/flows/tools/home.flow.yaml +34 -32
- package/templates/starter/flows/tools/home.locale.ar.yaml +8 -9
- package/templates/starter/flows/tools/home.locale.en.yaml +8 -0
- package/templates/starter/flows/tools/request.flow.yaml +95 -0
- package/templates/starter/flows/tools/request.locale.ar.yaml +14 -0
- package/templates/starter/flows/tools/request.locale.en.yaml +14 -0
- package/templates/starter/journeys/request.journey.yaml +12 -0
- package/templates/starter/locale.ar.yaml +6 -10
- package/templates/starter/locale.en.yaml +9 -0
- package/templates/starter/manifest.yaml +44 -45
- package/templates/starter/messages.ar.yaml +3 -10
- package/templates/starter/messages.en.yaml +19 -0
- package/templates/starter/prompts/identity.md +7 -5
- package/templates/starter/xrm.yaml +32 -0
- package/templates/starter/flows/tools/browse.flow.yaml +0 -31
- package/templates/starter/flows/tools/browse.locale.ar.yaml +0 -6
package/README.md
CHANGED
|
@@ -17,7 +17,7 @@ it alongside other tenants).
|
|
|
17
17
|
|
|
18
18
|
## Requirements
|
|
19
19
|
|
|
20
|
-
- **Node.js ≥
|
|
20
|
+
- **Node.js ≥ 22**
|
|
21
21
|
- Access to an **Octwin platform** (its base URL), a **tenant** (your workspace) on it, and a
|
|
22
22
|
**deploy token** (generated in the Octwin console — see [Authentication](#authentication)).
|
|
23
23
|
|
|
@@ -43,8 +43,10 @@ octwin init ./my-pack --id my-pack --description "My business bot"
|
|
|
43
43
|
cd ./my-pack
|
|
44
44
|
git init && git add -A && git commit -m "init pack"
|
|
45
45
|
|
|
46
|
-
# 2. Author it
|
|
47
|
-
# and
|
|
46
|
+
# 2. Author it. The starter is a bilingual (ar + en) AI Agent: a home menu, a visit request
|
|
47
|
+
# saved as a record, and a journey. Pull the authoring KB, add recipes, edit — pure YAML.
|
|
48
|
+
octwin platform-kb pull # guides + recipes; read .octwin/platform-kb/INDEX.md first
|
|
49
|
+
octwin recipe # the recipes you can add; `octwin recipe booking` writes one in
|
|
48
50
|
|
|
49
51
|
# 3. Point it at your platform — one command, no config file.
|
|
50
52
|
# It prints a link; approve it in the console and it saves a 30-day token
|
|
@@ -69,31 +71,37 @@ refused by name rather than leaving stdout empty.
|
|
|
69
71
|
|
|
70
72
|
| Command | What it does |
|
|
71
73
|
| --- | --- |
|
|
72
|
-
| `octwin init <dir>` | Scaffold a new pure-YAML pack into `<dir
|
|
73
|
-
| `octwin
|
|
74
|
+
| `octwin init <dir>` | Scaffold a new pure-YAML pack into `<dir>`: a bilingual (ar + en) starter — the manifest, a home menu, a visit request flow (the KB's collect recipe), `xrm.yaml`, a journey, `commands.yaml`, locale and message files — that passes the platform's full check with no warning. The pack id is the directory's own name (`./clinic` → `clinic`) unless `--id` says otherwise. Options: `--id`, `--description`, `--display-name`. |
|
|
75
|
+
| `octwin recipe [<module>]` | List the recipes in the pulled KB, or write one into this pack (`--dir`, `--dry-run`). Reads the recipe's starter files from the pulled guide, so there is no second copy to drift. Never overwrites: a file you already have is named, and a declaration you already have (your `xrm.yaml`) gets the recipe's part printed to merge, with the `flows:` / `tools:` lines to add. It also names any OTHER recipe this one needs and your pack lacks — a flow its buttons open, a journey id its `track:` names — so `octwin recipe booking` says up front that it needs handoff, journey and casework. Needs `octwin platform-kb pull`. |
|
|
76
|
+
| `octwin validate` | Fast offline checks (structure + pure-YAML rules + the checks the pulled KB drives + every literal journey id a `track:` / `track_event` names, against your own `journeys/`), then — **by default, with no login needed** — **the same validation the platform runs to load your pack**. Without a token and a `--project` it asks the platform's public validate route; with both it goes through your workspace and also confirms the project exists. When it cannot reach the platform, the LAST line says *"only the OFFLINE check ran — a PARTIAL check"* and why. `--remote` makes the full check required (not reaching it is an error); `--offline` runs only the subset. The full check covers every declaration file (`xrm.yaml`, `scheduling.yaml`, `worklist.yaml`, `roles.yaml`, `automation.yaml`, `integrations.yaml`, `surveys.yaml`, `taps.yaml`, `commands.yaml`, `journeys/`, `messages.<lang>.yaml`), the cross-file checks between them, and the **flow lint** — conventions the schema can't express, like an `assign:` whose value is a quoted literal or a `$t()` key with no namespace. These need template expansion and the platform's own schemas, which only the server has, so an offline ✓ does not cover them. A full-check ✓ and a successful deploy are the same answer by construction, not by convention. `octwin validate --require-kb` fails when the pulled KB is missing instead of skipping its checks (for CI); `octwin validate --strict-primitives` also type-checks LITERAL `args:` values against each primitive's input schema. |
|
|
74
77
|
| `octwin login` | Sign in to a platform URL **and make it the default target** (both stored in `~/.octwin/credentials.json`). With no `--token` it prints a link to approve in the console, then collects a 30-day token itself — nothing is pasted. The wait is bounded and resumable: run it again to keep waiting on the same request. `--url`, `--token`, `--wait <seconds>`, `--json`. |
|
|
75
78
|
| `octwin whoami` | Verify the saved/passed token is valid for a tenant. `--url`, `--tenant`. |
|
|
76
|
-
| `octwin deploy` | Upload + install the pack onto your tenant's project. `--seed` also runs the pack's demo seed. Says **nothing** about the public marketplace unless asked: `--request-listing` submits the pack for operator review (needs `listing.public: true` in the manifest too), `--withdraw-listing` retracts. Reports the **listing verdict** whenever one exists. |
|
|
77
|
-
| `octwin status` | Report what the platform has live for this pack — installed version, the **content sha** the instance loaded vs. the one the catalog holds (a redeploy of the *same* version changes it), its flows,
|
|
78
|
-
| `octwin pull <packId>` | Write a **deployed** pack's source back to disk — the inverse of `deploy`, and how a pack pushed from one machine is recovered. Defaults to the version installed on the target project; `--version` overrides, `--dir`
|
|
79
|
-
| `octwin chat "msg"` | Drive a turn through the dev web channel and print **every render with its tap ids**. `--as <handle>` picks the test user; `--tap "<tap-id>"` presses a rendered button/list row; `--json` dumps the raw envelopes. Each reply line says who sent it: plain `← …` is the AI Agent, `← [notify] …` a reminder or notification (never taken for the turn's reply), `← [operator: Name] …` a person in Live chat, `← [platform] …` a handoff line. |
|
|
79
|
+
| `octwin deploy` | Upload + install the pack onto your tenant's project. `--seed` also runs the pack's demo seed. Says **nothing** about the public marketplace unless asked: `--request-listing` submits the pack for operator review (needs `listing.public: true` in the manifest too), `--withdraw-listing` retracts. Reports the **listing verdict** whenever one exists. Sends what your copy was made from (`.octwin-base.json`, written by every pull and deploy): when someone published since — Tavi in the console, another deploy, a repo import — or the copy is a **lower** version, the deploy is **refused and nothing changes**; `octwin pull` then deploy again, or `--force` to replace the live version anyway. |
|
|
80
|
+
| `octwin status` | Report what the platform has live for this pack — installed version, the **content sha** the instance loaded vs. the one the catalog holds (a redeploy of the *same* version changes it), its flows, whether it is live on the public marketplace, and whether **your copy** is still the live content (if not, pull before you deploy). |
|
|
81
|
+
| `octwin pull <packId>` | Write a **deployed** pack's source back to disk — the inverse of `deploy`, and how a pack pushed from one machine is recovered. Defaults to the version installed on the target project; `--version` overrides. Writes into the folder you are in when it is this pack, else `./<packId>` (`--dir` overrides), and records it as the folder's base (`.octwin-base.json` — commit it). Replaces only files that still match your last pull or deploy: a file you changed since **stops** the pull, so save your edit first, or `--force` overwrites it. You may pull a pack your tenant **owns**. |
|
|
82
|
+
| `octwin chat "msg"` | Drive a turn through the dev web channel and print **every render with its tap ids**. `--as <handle>` picks the test user; `--tap "<tap-id>"` presses a rendered button/list row; `--json` dumps the raw envelopes. Each reply line says who sent it: plain `← …` is the AI Agent, `← [notify] …` a reminder or notification (never taken for the turn's reply), `← [operator: Name] …` a person in Live chat, `← [platform] …` a handoff line. `octwin chat --press "<label>"` taps a button by its label — the way through a form or checkout, whose tap ids change; `octwin chat --script <file>` drives a whole conversation, one turn per line, over one connection (`press:`, `tap:`, `media:` lines). |
|
|
80
83
|
| `octwin logs` | List recent conversations (handle, status, last activity; `--as` filters), or show one conversation's full event timeline — including what each turn rendered. `--json` for raw payloads. |
|
|
81
|
-
| `octwin records` | Inspect the pack's XRM data (needs a `records:read` token). No args = list entities. `<entity> --search "<words>"` runs the entity's ranked search (it must declare `search:`) and prints each match's score. Writes (`records:write`): `create`, `patch`, `stage`, `note`, and `archive <id>` / `restore <id>` — there is no delete; archive takes a record (test data too) out of every list and count, and restore brings it back. |
|
|
82
|
-
| `octwin work` | The work inbox: worked records across queues, one item + its timeline and decisions, or `--queues` for queue keys + open counts. Casework is one shape of it — the command spans every entity a pack works. |
|
|
83
|
-
| `octwin projects` | The `--project <slug>` values this token can name, with the plan's project cap. `--archived` includes archived ones. A `pack:deploy` token reaches it — it names a project in every other command, so this turns "guess the slug" into "read the list". |
|
|
84
|
-
| `octwin agents` | The agent roster with each agent's **effective** model / history window and **which layer set it** (project override → platform default → pack manifest) — an operator platform default can override what your manifest declares. `--prompt` prints the exact system prompt the LLM sees. Needs `agents:read`. |
|
|
85
|
-
| `octwin orders` | The orders a conversation produced. No args = the list; with a `reference_id` = line items, the subtotal/tax/shipping/discount/total breakdown, `payment_ref`, and the allowed transitions. Needs `orders:read` + the `orders` plan feature. |
|
|
86
|
-
| `octwin analytics` | Stage-by-stage conversion for **any** entity declared with a `pipeline:` (`--overview` / `--milestones` / `--trends` / `--cost`; `--stage <id>` lists the records currently at a stage). Needs `records:read`. |
|
|
87
|
-
| `octwin catalog` | Commerce products with price / availability / stock, plus the WhatsApp catalog binding. `--readiness` runs the Meta Graph checklist. Needs `catalog:read` + the `catalog` plan feature. |
|
|
88
|
-
| `octwin scheduling` | The scheduling engine's state, or `--slots <resourceRecordId>` for the slots one bookable resource actually computes — how you verify the availability rules `deploy --seed` created. Needs `scheduling:read`. |
|
|
89
|
-
| `octwin automation` | The jobs your pack's automation declaration produced — status, interval and each one's **last result** (matched / acted / errors) — under a health line counted in SQL. `campaigns` lists the campaigns. Jobs are derived from declarations, so there is no `create`. Needs `automation:read`. |
|
|
90
|
-
| `octwin integrations` | What the pack **declares** beside what is actually **configured**, and it flags the gap: a connection declared and never configured is the commonest reason an integration silently never fires, and neither list alone shows it. `preflight <key>` diagnoses without calling out (`integrations:read`); `deliveries [id]` is the outbound log; `events` is what arrived inbound. Needs `integrations:read`. |
|
|
91
|
-
| `octwin journeys` | The customer journeys your pack declares, measured: `--funnel` (default) · `--overview` · `--goals` · `--trends` · `--cost` · `--definition` (what was declared, works with no traffic), plus `--stage <id>` for the runs sitting at a stage now. Same flag grammar as `octwin analytics` — a journey funnel and an entity funnel are the same question about different subjects. Needs `journeys:read`. |
|
|
92
|
-
| `octwin performance` | The project's business indicators — value produced, conversion, duration — each with its delta against the previous window and a `why` naming the declaration it came from. `--detail` adds the breakdown. Needs `records:read`, **not** a `performance:*` scope (there is none). |
|
|
84
|
+
| `octwin records` | Inspect the pack's XRM data (needs a `records:read` token). No args = list entities. `<entity> --search "<words>"` runs the entity's ranked search (it must declare `search:`) and prints each match's score. Writes (`records:write`): `create`, `patch`, `stage`, `note`, and `archive <id>` / `restore <id>` — there is no delete; archive takes a record (test data too) out of every list and count, and restore brings it back. Lists page with `octwin records <entity> --limit 50 --offset n`. |
|
|
85
|
+
| `octwin work` | The work inbox: worked records across queues, one item + its timeline and decisions, or `--queues` for queue keys + open counts. Casework is one shape of it — the command spans every entity a pack works. Lists page with `octwin work --limit 50 --offset n`; `octwin work --unrouted` shows only the items in no queue. |
|
|
86
|
+
| `octwin projects` | The `--project <slug>` values this token can name, with the plan's project cap. `--archived` includes archived ones. A `pack:deploy` token reaches it — it names a project in every other command, so this turns "guess the slug" into "read the list". `octwin projects create "<name>" [--slug <slug>] [--pack <packId>]` makes one; `octwin projects rm <slug> --yes` HARD-deletes it (without `--yes` it only previews). Both need `projects:write`. |
|
|
87
|
+
| `octwin agents` | The agent roster with each agent's **effective** model / history window and **which layer set it** (project override → platform default → pack manifest) — an operator platform default can override what your manifest declares. `--prompt` prints the exact system prompt the LLM sees. Needs `agents:read`. `octwin agents set <ref> --enabled true|false --overlay "…"|none` turns an agent off or adds a project instruction overlay (see the writes table). |
|
|
88
|
+
| `octwin orders` | The orders a conversation produced. No args = the list; with a `reference_id` = line items, the subtotal/tax/shipping/discount/total breakdown, `payment_ref`, and the allowed transitions. Needs `orders:read` + the `orders` plan feature. Filter with `octwin orders --status s --payment p --limit 50 --offset n`. |
|
|
89
|
+
| `octwin analytics` | Stage-by-stage conversion for **any** entity declared with a `pipeline:` (`--overview` / `--milestones` / `--trends` / `--cost`; `--stage <id>` lists the records currently at a stage). Needs `records:read`. Page `--stage` with `octwin analytics <entity> --stage <id> --limit n --offset n`. |
|
|
90
|
+
| `octwin catalog` | Commerce products with price / availability / stock, plus the WhatsApp catalog binding. `--readiness` runs the Meta Graph checklist. Needs `catalog:read` + the `catalog` plan feature. Page with `octwin catalog --limit n --offset n`. |
|
|
91
|
+
| `octwin scheduling` | The scheduling engine's state, or `--slots <resourceRecordId>` for the slots one bookable resource actually computes — how you verify the availability rules `deploy --seed` created. Needs `scheduling:read`. `octwin scheduling --slots <resourceRecordId> --from YYYY-MM-DD --days n` reads one resource's computed slots. |
|
|
92
|
+
| `octwin automation` | The jobs your pack's automation declaration produced — status, interval and each one's **last result** (matched / acted / errors) — under a health line counted in SQL. `campaigns` lists the campaigns. Jobs are derived from declarations, so there is no `create`. Needs `automation:read`. `octwin automation campaigns` (or `--campaigns`) lists campaigns; page with `octwin automation --limit n --offset n`. |
|
|
93
|
+
| `octwin integrations` | What the pack **declares** beside what is actually **configured**, and it flags the gap: a connection declared and never configured is the commonest reason an integration silently never fires, and neither list alone shows it. `preflight <key>` diagnoses without calling out (`integrations:read`); `deliveries [id]` is the outbound log; `events` is what arrived inbound. Needs `integrations:read`. `octwin integrations deliveries --status s --operation id --limit n --offset n` is the outbound delivery log. |
|
|
94
|
+
| `octwin journeys` | The customer journeys your pack declares, measured: `--funnel` (default) · `--overview` · `--goals` · `--trends` · `--cost` · `--definition` (what was declared, works with no traffic), plus `--stage <id>` for the runs sitting at a stage now. Same flag grammar as `octwin analytics` — a journey funnel and an entity funnel are the same question about different subjects. Needs `journeys:read`. Page `--stage` with `octwin journeys <id> --stage <stageId> --limit n --offset n`. |
|
|
95
|
+
| `octwin performance` | The project's business indicators — value produced, conversion, duration — each with its delta against the previous window and a `why` naming the declaration it came from. `--detail` adds the breakdown. Needs `records:read`, **not** a `performance:*` scope (there is none). `octwin performance --range <days>` sets the window and `octwin performance --channel <whatsapp|web>` narrows every figure to one channel — the console's two controls. |
|
|
93
96
|
| `octwin usage` | Model calls, tokens and cost, by model / kind / agent / channel. Project when one is pinned, workspace otherwise. Needs no particular scope. **Model spend only** — WhatsApp/Meta message billing is operator-only and no API token can read it. |
|
|
97
|
+
| `octwin charts [<key>]` | The pack's own `charts:` (xrm.yaml), as the owner's dashboard draws them: the list, or one chart's figure, parts or points. `octwin charts <key> --from YYYY-MM-DD --to YYYY-MM-DD` sets the window; `--json`. Needs `records:read`. |
|
|
98
|
+
| `octwin handoff [<id>]` | The Live chat desk, read-only: the handoffs in a bucket (`octwin handoff --bucket waiting\|mine\|all\|ended --limit n --offset n`), or one with its transcript; `--json`. Needs `work:read` + the `live_chat` plan feature. Accepting, answering and returning one stay in the console — they need a signed-in person, and a token is not one. |
|
|
99
|
+
| `octwin surveys [<key>]` | The declared surveys with their responses and headline score, or one survey's questions, rollup and recent answers (`octwin surveys <key> --limit n --offset n` pages them); `--json`. Needs `records:read`. |
|
|
100
|
+
| `octwin seed` | Apply the pack's demo data to the project it is installed on, without redeploying — xrm `demo:` rows, scheduling availability, the commerce catalog, the demo operator topology. Idempotent: each row is found again by its handle and updated. `octwin seed --reset` archives every row the demo loaded and loads it again; `octwin seed --pack <packId>` only when a project runs more than one. |
|
|
101
|
+
| `octwin memos` | Read what the platform told you — a reply to your `octwin feedback`, or a notice to every author (a new capability, a deprecation, a breaking change). Reading marks them read; `octwin memos --all` re-reads history and acks nothing; `--json` to branch on `severity`. |
|
|
94
102
|
| `octwin media generate "<prompt>"` | AI-generate an image, store it as a public asset, and print its `MEDIA-` handle + serve URL. `--out` downloads the bytes (WhatsApp renders only `.png`/`.jpg`); `--json`. Pairs with `octwin chat --media` to drive media-collect flows. Needs `media:generate`. |
|
|
95
103
|
| `octwin platform-kb pull` | Pull the platform's capability reference into `.octwin/platform-kb/` for the **`octwin-pack`** Claude Code authoring plugin: guides as markdown, plus **one JSON file per capability** (`primitives/record_list.json`, `render-intents/carousel.json`, `declarations/xrm.json`, …) and **three maps** — `INDEX.md` (the corpus, by family and size), `SYMBOLS.md` (every name → its exact file; grep this), `OUTLINE.md` (every heading with its line number). **No token needed** — the reference is served anonymously. `--if-stale` skips the download when your copy is current (cheap enough for every session); `--check` writes nothing and exits 0 current / 2 stale / 1 could-not-tell. |
|
|
96
|
-
| `octwin test` | Alias for `octwin validate --remote` — the platform's full check, required (a skipped full check is an error). |
|
|
104
|
+
| `octwin test` | Alias for `octwin validate --remote` (it takes `octwin test --require-kb --strict-primitives`, as validate does; `--offline` contradicts it) — the platform's full check, required (a skipped full check is an error). |
|
|
97
105
|
| `octwin feedback` | Submit this pack's `FEEDBACK.md` to the platform team, with the pack version, your CLI version and the `content_hash` of the capability reference you pulled — the two facts that separate a real platform gap from something already fixed or a stale KB. |
|
|
98
106
|
| `octwin help` | Show usage. Every subcommand also answers `--help`. |
|
|
99
107
|
|
|
@@ -105,19 +113,19 @@ lists the verbs and their exact flags.
|
|
|
105
113
|
|
|
106
114
|
| Command | Verbs |
|
|
107
115
|
| --- | --- |
|
|
108
|
-
| `octwin records` | `create <entity> --set k=v` · `patch <id> --entity <e>` · `stage <id> --to <s
|
|
109
|
-
| `octwin work` | `assign <id> --to user:<uuid>\|none` · `note` · `
|
|
110
|
-
| `octwin orders` | `transition <ref> --to <status>` · `refund <ref> --force` |
|
|
116
|
+
| `octwin records` | `create <entity> --set k=v [--stage s] [--contact <id>]` (`--fields-json '{…}'` for nested values) · `patch <id> --entity <e>` · `stage <id> --to <s> [--note "…"]` · `note <id> "…"` · `tasks` · `task complete <id> [--outcome done|cancelled] [--note "…"]` |
|
|
117
|
+
| `octwin work` | `assign <id> --to user:<uuid>\|none` · `note` · `stage <id> --to <stage> [--note "…"]` · `decide <id> --action <a> [--param k=v] [--note "…"] [--dry-run]` (the dry run needs only `work:read`) |
|
|
118
|
+
| `octwin orders` | `transition <ref> --to <status>` · `refund <ref> [--reason "…"] [--mark-returned] --force` |
|
|
111
119
|
| `octwin catalog` | `availability <sku> --to "in stock"` · `stock <sku> [--set-on-hand n]` |
|
|
112
|
-
| `octwin scheduling` | `rules --resource <id>` · `rule add
|
|
113
|
-
| `octwin agents` | `set <ref> [--model m] [--enable-tool t] [--disable-tool t]` |
|
|
120
|
+
| `octwin scheduling` | `rules --resource <id>` · `rule add --resource <id> --dow 1 --start 09:00 --end 17:00 [--slot-minutes 30] [--capacity 1]` · `rule rm <ruleId>` · `exception add --resource <id> --date YYYY-MM-DD --kind closed\|extra [--start --end]` · `exception rm <id>` |
|
|
121
|
+
| `octwin agents` | `set <ref> [--model m] [--enabled true\|false] [--overlay "…"\|none] [--enable-tool t] [--disable-tool t]` |
|
|
114
122
|
| `octwin automation` | `run <jobId>` · `pause\|resume <jobId>` · `send <campaignId>` — the id may be the declaration **key** the list prints; the CLI resolves it to the uuid the route wants |
|
|
115
123
|
| `octwin integrations` | `test <key>` (a live call to the connection's `health:` operation) · `retry\|cancel\|send-now <deliveryId>` |
|
|
116
124
|
|
|
117
125
|
`--set k=v` coerces JSON scalars (`--set rating=4.5` sends a number); `--fields-json` takes anything
|
|
118
126
|
nested. Destructive verbs want `--force` rather than a prompt — the CLI is non-interactive by
|
|
119
|
-
design. `
|
|
120
|
-
committing, and needs only `
|
|
127
|
+
design. `work decide --dry-run` previews the customer-facing copy and the resulting stage without
|
|
128
|
+
committing, and needs only `work:read`.
|
|
121
129
|
|
|
122
130
|
Every command that talks to the platform accepts `--dir <path>` (the pack directory; defaults to
|
|
123
131
|
the current directory) plus the target overrides `--url` / `--tenant` / `--project` / `--token`.
|