@harness-lab/cli 0.2.7 → 0.2.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/assets/workshop-bundle/SKILL.md +16 -0
- package/assets/workshop-bundle/bundle-manifest.json +9 -9
- package/assets/workshop-bundle/content/project-briefs/code-review-helper.md +10 -10
- package/assets/workshop-bundle/docs/harness-cli-foundation.md +8 -1
- package/assets/workshop-bundle/workshop-blueprint/README.md +3 -2
- package/assets/workshop-bundle/workshop-blueprint/agenda.json +58 -16
- package/assets/workshop-bundle/workshop-blueprint/day-structure.md +3 -3
- package/assets/workshop-bundle/workshop-skill/facilitator.md +54 -0
- package/package.json +1 -1
- package/src/client.js +6 -0
- package/src/run-cli.js +77 -2
|
@@ -215,6 +215,18 @@ This is a facilitator-only command — do not surface to participants.
|
|
|
215
215
|
Show the current instance state, agenda phase, facilitator list, and team count.
|
|
216
216
|
Requires active facilitator session.
|
|
217
217
|
|
|
218
|
+
### `workshop facilitator list-instances`
|
|
219
|
+
|
|
220
|
+
List the facilitator-visible workshop instance registry.
|
|
221
|
+
Prefer invoking `harness workshop list-instances` over raw API scripts or local session-file inspection.
|
|
222
|
+
Use this when the facilitator needs to discover what currently exists on a shared dashboard before choosing an explicit instance for reset, update, or agenda work.
|
|
223
|
+
|
|
224
|
+
### `workshop facilitator show-instance <instance-id>`
|
|
225
|
+
|
|
226
|
+
Inspect one explicit workshop instance.
|
|
227
|
+
Prefer invoking `harness workshop show-instance <instance-id>` over raw API scripts.
|
|
228
|
+
Use this when the facilitator needs the full record for one instance rather than the deployment-default runtime status returned by `workshop facilitator status`.
|
|
229
|
+
|
|
218
230
|
### `workshop facilitator grant <email> <role>`
|
|
219
231
|
|
|
220
232
|
Grant a Neon Auth user access to the current workshop instance.
|
|
@@ -249,6 +261,10 @@ Prefer invoking `harness workshop update-instance` over raw API scripts.
|
|
|
249
261
|
Use this when the facilitator wants to correct or refine date, venue, room, address, or event title without resetting the instance.
|
|
250
262
|
Support `contentLang` changes explicitly so facilitators can choose workshop delivery language per instance without changing admin UI language.
|
|
251
263
|
|
|
264
|
+
Facilitator discovery rule:
|
|
265
|
+
- for routine discovery, use `harness workshop list-instances` and `harness workshop show-instance`
|
|
266
|
+
- do not read local CLI session files or improvise authenticated `node -e` fetch scripts unless you are diagnosing the CLI itself
|
|
267
|
+
|
|
252
268
|
### `workshop facilitator reset-instance <instance-id>`
|
|
253
269
|
|
|
254
270
|
Reset one existing workshop instance from the selected blueprint template. Requires facilitator session.
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
{
|
|
2
2
|
"manifestVersion": 1,
|
|
3
3
|
"bundleName": "harness-lab-workshop",
|
|
4
|
-
"bundleVersion": "0.2.
|
|
5
|
-
"contentHash": "
|
|
4
|
+
"bundleVersion": "0.2.8",
|
|
5
|
+
"contentHash": "6194a59089ff94131b647282c1b5e7574a6a9d112c48b4b9d58b600f5775736a",
|
|
6
6
|
"files": [
|
|
7
7
|
{
|
|
8
8
|
"path": "content/challenge-cards/.gitkeep",
|
|
@@ -42,7 +42,7 @@
|
|
|
42
42
|
},
|
|
43
43
|
{
|
|
44
44
|
"path": "content/project-briefs/code-review-helper.md",
|
|
45
|
-
"sha256": "
|
|
45
|
+
"sha256": "3e174ff0d097fe132088774042f9db58c9c2494613d66950bdd423116bd7986d"
|
|
46
46
|
},
|
|
47
47
|
{
|
|
48
48
|
"path": "content/project-briefs/devtoolbox-cli.md",
|
|
@@ -102,7 +102,7 @@
|
|
|
102
102
|
},
|
|
103
103
|
{
|
|
104
104
|
"path": "docs/harness-cli-foundation.md",
|
|
105
|
-
"sha256": "
|
|
105
|
+
"sha256": "f3b6125a4575c27dcb7b88474003f2a9b189a4b1b25bfaa462861571b69f7a51"
|
|
106
106
|
},
|
|
107
107
|
{
|
|
108
108
|
"path": "docs/learner-reference-gallery.md",
|
|
@@ -134,11 +134,11 @@
|
|
|
134
134
|
},
|
|
135
135
|
{
|
|
136
136
|
"path": "SKILL.md",
|
|
137
|
-
"sha256": "
|
|
137
|
+
"sha256": "de24b73c431855143630f6d312d9bb2af0a16178c2c70f928c5c3a426e569777"
|
|
138
138
|
},
|
|
139
139
|
{
|
|
140
140
|
"path": "workshop-blueprint/agenda.json",
|
|
141
|
-
"sha256": "
|
|
141
|
+
"sha256": "91b4037578ce61d172e09941089b97180322552cb42bb52de87b3956e60b1ed0"
|
|
142
142
|
},
|
|
143
143
|
{
|
|
144
144
|
"path": "workshop-blueprint/control-surfaces.md",
|
|
@@ -146,7 +146,7 @@
|
|
|
146
146
|
},
|
|
147
147
|
{
|
|
148
148
|
"path": "workshop-blueprint/day-structure.md",
|
|
149
|
-
"sha256": "
|
|
149
|
+
"sha256": "ffecae258211cef2430112ca25e1ff59658cac729ea2a07b9cac48e9a2a6244e"
|
|
150
150
|
},
|
|
151
151
|
{
|
|
152
152
|
"path": "workshop-blueprint/edit-boundaries.md",
|
|
@@ -158,7 +158,7 @@
|
|
|
158
158
|
},
|
|
159
159
|
{
|
|
160
160
|
"path": "workshop-blueprint/README.md",
|
|
161
|
-
"sha256": "
|
|
161
|
+
"sha256": "badb477ecfef7df163ec41c72c39e04bcde2a5a723c1b01bf2e91ed38924e903"
|
|
162
162
|
},
|
|
163
163
|
{
|
|
164
164
|
"path": "workshop-blueprint/teaching-spine.md",
|
|
@@ -182,7 +182,7 @@
|
|
|
182
182
|
},
|
|
183
183
|
{
|
|
184
184
|
"path": "workshop-skill/facilitator.md",
|
|
185
|
-
"sha256": "
|
|
185
|
+
"sha256": "f0e977df5979d0d218eabad026b66ecefa90802c71dc8a9468959334570f1c1c"
|
|
186
186
|
},
|
|
187
187
|
{
|
|
188
188
|
"path": "workshop-skill/follow-up-package.md",
|
|
@@ -2,30 +2,30 @@
|
|
|
2
2
|
|
|
3
3
|
## Problém
|
|
4
4
|
|
|
5
|
-
Code review bývá nevyrovnané. Některé změny projdou s dobrým checklistem a jasným popisem rizik, jiné bez společného rámce. Reviewer pak improvizuje, autor neví, co má ověřit předem, a tým ztrácí konzistenci
|
|
5
|
+
Code review bývá nevyrovnané. Některé změny projdou s dobrým checklistem a jasným popisem rizik, jiné bez společného rámce. Reviewer pak improvizuje, autor neví, co má ověřit předem, a tým ztrácí konzistenci právě tam, kde by měl být nejpřesnější.
|
|
6
6
|
|
|
7
|
-
Vaším úkolem je navrhnout nástroj, který z diffu nebo změny vytvoří použitelný review checklist.
|
|
7
|
+
Vaším úkolem je navrhnout nástroj, který z diffu nebo změny vytvoří použitelný review checklist a zároveň jasně oddělí jistotu, heuristiku a místa, kde je pořád potřeba lidský úsudek.
|
|
8
8
|
|
|
9
9
|
## User stories
|
|
10
10
|
|
|
11
|
-
- Jako reviewer chci z diffu rychle získat checklist rizik, otázek a míst, na která se zaměřit.
|
|
12
|
-
- Jako autor změny chci vědět, co mám
|
|
11
|
+
- Jako reviewer chci z diffu rychle získat checklist změněných hranic, rizik, otázek a míst, na která se zaměřit.
|
|
12
|
+
- Jako autor změny chci vědět, co mám ověřit ještě před samotným review.
|
|
13
13
|
- Jako tým po rotaci chci navázat na heuristiky, které původní tým objevil, místo abych je znovu vymýšlel.
|
|
14
14
|
|
|
15
15
|
## Architektonické poznámky
|
|
16
16
|
|
|
17
|
-
- Může jít o CLI, web nebo jednoduchý skript. Důležitý je jasný tok `diff →
|
|
18
|
-
- Musí být zřejmé, jaké vstupy nástroj
|
|
19
|
-
- Přidejte seed diff nebo `examples/`, aby šlo workflow lokálně ověřit.
|
|
20
|
-
-
|
|
17
|
+
- Může jít o CLI, web nebo jednoduchý skript. Důležitý je jasný tok `diff → rubric → checklist`.
|
|
18
|
+
- Musí být zřejmé, jaké vstupy nástroj očekává, co umí označit jistě a co naopak zůstává heuristické.
|
|
19
|
+
- Přidejte seed diff nebo `examples/`, aby šlo workflow lokálně ověřit a další tým rychle přidal nové pravidlo.
|
|
20
|
+
- Nástroj má pomáhat reviewerovi, ne předstírat neomylnost.
|
|
21
21
|
|
|
22
22
|
## Hotovo když
|
|
23
23
|
|
|
24
24
|
- Nástroj vytvoří review checklist ze seed diffu.
|
|
25
|
-
- Výstup odlišuje jistá zjištění od
|
|
25
|
+
- Výstup odlišuje jistá zjištění od doporučení, hypotéz a bodů pro lidský úsudek.
|
|
26
26
|
- Je jasné, jak přidat nové pravidlo nebo heuristiku bez dlouhého onboardingu.
|
|
27
27
|
- Další tým může během několika minut pokračovat v rozvoji bez chaosu.
|
|
28
28
|
|
|
29
29
|
## První krok pro agenta
|
|
30
30
|
|
|
31
|
-
Nezačínej kódem. Nejdřív napiš
|
|
31
|
+
Nezačínej kódem. Nejdřív napiš review rubric, tok vstupů a definici toho, co znamená dobrý checklist. Ukaž, kde je jistota, kde heuristika a co musí posoudit člověk. Teprve potom navrhni první implementační slice.
|
|
@@ -8,7 +8,7 @@ Current implementation in this repo:
|
|
|
8
8
|
|
|
9
9
|
- lives in the repository `harness-cli/` package and ships publicly as `@harness-lab/cli`
|
|
10
10
|
- distributes a portable participant workshop skill bundle through `harness skill install`
|
|
11
|
-
- covers `auth login/logout/status` plus `workshop status/create-instance/update-instance/reset-instance/prepare/remove-instance/archive/phase set`
|
|
11
|
+
- covers `auth login/logout/status` plus `workshop status/list-instances/show-instance/create-instance/update-instance/reset-instance/prepare/remove-instance/archive/phase set`
|
|
12
12
|
- targets the existing shared dashboard facilitator APIs
|
|
13
13
|
- is tested for browser/device auth, local-dev Basic Auth fallback, and cookie-backed Neon bootstrap fallback
|
|
14
14
|
- stores sessions in a local file under `HARNESS_CLI_HOME` or `~/.harness` by default
|
|
@@ -39,6 +39,8 @@ Required commands:
|
|
|
39
39
|
- `harness auth logout`
|
|
40
40
|
- `harness auth status`
|
|
41
41
|
- `harness workshop status`
|
|
42
|
+
- `harness workshop list-instances`
|
|
43
|
+
- `harness workshop show-instance <instance-id>`
|
|
42
44
|
- `harness workshop create-instance`
|
|
43
45
|
- `harness workshop update-instance`
|
|
44
46
|
- `harness workshop reset-instance <instance-id>`
|
|
@@ -89,6 +91,10 @@ Current target-selection order:
|
|
|
89
91
|
|
|
90
92
|
Current command posture:
|
|
91
93
|
|
|
94
|
+
- explicit workspace-discovery commands:
|
|
95
|
+
- `harness workshop list-instances`
|
|
96
|
+
- explicit target required:
|
|
97
|
+
- `harness workshop show-instance <instance-id>`
|
|
92
98
|
- explicit target required:
|
|
93
99
|
- `harness workshop update-instance <instance-id>`
|
|
94
100
|
- `harness workshop reset-instance <instance-id>`
|
|
@@ -105,6 +111,7 @@ Current discoverability path:
|
|
|
105
111
|
|
|
106
112
|
- facilitators can inspect available workshop instances through the dashboard workspace view
|
|
107
113
|
- the same platform-scoped list lives behind the authenticated instances API surface at `/api/workshop/instances`
|
|
114
|
+
- the CLI should expose that list directly so facilitator skills do not need session-file inspection or raw authenticated scripts for routine discovery
|
|
108
115
|
|
|
109
116
|
For the current facilitator lifecycle slice:
|
|
110
117
|
|
|
@@ -39,7 +39,7 @@ Do not use this folder for live event state. Real dates, rooms, rosters, checkpo
|
|
|
39
39
|
### Structured data
|
|
40
40
|
|
|
41
41
|
- [`agenda.json`](agenda.json)
|
|
42
|
-
Public-readable workshop
|
|
42
|
+
Public-readable 10-phase mirror of the workshop day and workshop metadata.
|
|
43
43
|
|
|
44
44
|
## Related Runtime Documents
|
|
45
45
|
|
|
@@ -51,5 +51,6 @@ For maintainers working in the source repository, the runtime-facing structured
|
|
|
51
51
|
|
|
52
52
|
- `docs/workshop-content-language-architecture.md`
|
|
53
53
|
- `dashboard/lib/workshop-blueprint-agenda.json`
|
|
54
|
+
- `dashboard/lib/workshop-blueprint-localized-content.ts`
|
|
54
55
|
|
|
55
|
-
Treat those as maintainer/source-repo references, not as portable participant-bundle docs.
|
|
56
|
+
Treat those as maintainer/source-repo references, not as portable participant-bundle docs. The public `agenda.json` file should stay aligned with the same phase structure, but it is not the runtime import source.
|
|
@@ -1,21 +1,23 @@
|
|
|
1
1
|
{
|
|
2
|
-
"version":
|
|
2
|
+
"version": 2,
|
|
3
3
|
"blueprintId": "harness-lab-core-day",
|
|
4
4
|
"title": "Harness Lab",
|
|
5
|
-
"subtitle": "
|
|
5
|
+
"subtitle": "Public-readable 10-phase mirror of the Harness Lab workshop day",
|
|
6
|
+
"presentationMode": "public-readable-mirror",
|
|
7
|
+
"sourceNote": "Runtime imports come from dashboard/lib/workshop-blueprint-agenda.json plus dashboard/lib/workshop-blueprint-localized-content.ts.",
|
|
6
8
|
"principles": [
|
|
7
|
-
"
|
|
8
|
-
"
|
|
9
|
-
"
|
|
9
|
+
"Context before generation",
|
|
10
|
+
"Verification is the trust boundary",
|
|
11
|
+
"Work so another team can continue"
|
|
10
12
|
],
|
|
11
13
|
"phases": [
|
|
12
14
|
{
|
|
13
15
|
"id": "opening",
|
|
14
16
|
"order": 1,
|
|
15
|
-
"label": "
|
|
17
|
+
"label": "Opening and framing",
|
|
16
18
|
"startTime": "09:10",
|
|
17
19
|
"kind": "shared",
|
|
18
|
-
"goal": "
|
|
20
|
+
"goal": "Shift the room from prompt-hackathon expectations to continuation-quality discipline."
|
|
19
21
|
},
|
|
20
22
|
{
|
|
21
23
|
"id": "talk",
|
|
@@ -23,31 +25,71 @@
|
|
|
23
25
|
"label": "Context is King",
|
|
24
26
|
"startTime": "09:40",
|
|
25
27
|
"kind": "shared",
|
|
26
|
-
"goal": "
|
|
28
|
+
"goal": "Turn context into a precise thesis: AGENTS.md, plans, and checks are working infrastructure, not polish."
|
|
27
29
|
},
|
|
28
30
|
{
|
|
29
|
-
"id": "
|
|
31
|
+
"id": "demo",
|
|
30
32
|
"order": 3,
|
|
33
|
+
"label": "Demo",
|
|
34
|
+
"startTime": "10:05",
|
|
35
|
+
"kind": "shared",
|
|
36
|
+
"goal": "Show one compact workflow story: context, planning, implementation, review, and safe fallback moves."
|
|
37
|
+
},
|
|
38
|
+
{
|
|
39
|
+
"id": "build-1",
|
|
40
|
+
"order": 4,
|
|
31
41
|
"label": "Build Phase 1",
|
|
32
42
|
"startTime": "10:30",
|
|
33
43
|
"kind": "team",
|
|
34
|
-
"goal": "
|
|
44
|
+
"goal": "Before lunch, get every team to a navigable repo, AGENTS.md, a plan, one explicit check, and a first reviewed slice."
|
|
45
|
+
},
|
|
46
|
+
{
|
|
47
|
+
"id": "intermezzo-1",
|
|
48
|
+
"order": 5,
|
|
49
|
+
"label": "Intermezzo 1",
|
|
50
|
+
"startTime": "11:40",
|
|
51
|
+
"kind": "shared",
|
|
52
|
+
"goal": "Surface one change, one proof, and one next move from the room before lunch momentum slips."
|
|
53
|
+
},
|
|
54
|
+
{
|
|
55
|
+
"id": "lunch-reset",
|
|
56
|
+
"order": 6,
|
|
57
|
+
"label": "Lunch Reset",
|
|
58
|
+
"startTime": "12:15",
|
|
59
|
+
"kind": "shared",
|
|
60
|
+
"goal": "Frame lunch as a handoff preparation point, not as a pause between unrelated workshop blocks."
|
|
35
61
|
},
|
|
36
62
|
{
|
|
37
63
|
"id": "rotation",
|
|
38
|
-
"order":
|
|
39
|
-
"label": "
|
|
64
|
+
"order": 7,
|
|
65
|
+
"label": "Continuation Shift",
|
|
40
66
|
"startTime": "13:30",
|
|
41
67
|
"kind": "team",
|
|
42
|
-
"goal": "
|
|
68
|
+
"goal": "Force silent repo reading, diagnosis, and explicit continuation before anyone edits code."
|
|
69
|
+
},
|
|
70
|
+
{
|
|
71
|
+
"id": "build-2",
|
|
72
|
+
"order": 8,
|
|
73
|
+
"label": "Build Phase 2",
|
|
74
|
+
"startTime": "14:05",
|
|
75
|
+
"kind": "team",
|
|
76
|
+
"goal": "Turn continuation friction into better repo guidance, stronger checks, and clearer next moves."
|
|
77
|
+
},
|
|
78
|
+
{
|
|
79
|
+
"id": "intermezzo-2",
|
|
80
|
+
"order": 9,
|
|
81
|
+
"label": "Intermezzo 2",
|
|
82
|
+
"startTime": "15:05",
|
|
83
|
+
"kind": "shared",
|
|
84
|
+
"goal": "Name which repo signals actually saved time during continuation and which failures repeated."
|
|
43
85
|
},
|
|
44
86
|
{
|
|
45
87
|
"id": "reveal",
|
|
46
|
-
"order":
|
|
47
|
-
"label": "Reveal
|
|
88
|
+
"order": 10,
|
|
89
|
+
"label": "Reveal and reflection",
|
|
48
90
|
"startTime": "15:45",
|
|
49
91
|
"kind": "shared",
|
|
50
|
-
"goal": "
|
|
92
|
+
"goal": "Turn the day into reusable practice: what helped continuation, what failed, and what should change next week."
|
|
51
93
|
}
|
|
52
94
|
],
|
|
53
95
|
"runtimeImport": {
|
|
@@ -147,8 +147,8 @@ The day should not feel like separate agenda cards. Each phase should change wha
|
|
|
147
147
|
- `AGENTS.md` as a table of contents that points to deeper sources of truth
|
|
148
148
|
- small, continuous garbage collection before bad patterns spread
|
|
149
149
|
|
|
150
|
-
##
|
|
150
|
+
## Agenda Mirror
|
|
151
151
|
|
|
152
|
-
The
|
|
152
|
+
The public-readable 10-phase mirror lives in [`agenda.json`](agenda.json).
|
|
153
153
|
|
|
154
|
-
Runtime workshop instances import from
|
|
154
|
+
Runtime workshop instances import from the maintained dashboard blueprint source pair and then track live phase position, reveal state, teams, and checkpoints locally in the private runtime layer.
|
|
@@ -65,6 +65,59 @@ Show:
|
|
|
65
65
|
- facilitator list with roles
|
|
66
66
|
- team count
|
|
67
67
|
|
|
68
|
+
Use this for the current default or selected workshop context.
|
|
69
|
+
If the facilitator needs the full workspace registry first, use `list-instances` instead of probing local session files or writing raw authenticated fetch scripts.
|
|
70
|
+
|
|
71
|
+
### `/workshop facilitator list-instances`
|
|
72
|
+
|
|
73
|
+
Preferred path:
|
|
74
|
+
|
|
75
|
+
```bash
|
|
76
|
+
harness workshop list-instances
|
|
77
|
+
```
|
|
78
|
+
|
|
79
|
+
Show:
|
|
80
|
+
- facilitator-visible instance ids
|
|
81
|
+
- template id
|
|
82
|
+
- status
|
|
83
|
+
- content language
|
|
84
|
+
- event title and room metadata when present
|
|
85
|
+
|
|
86
|
+
Raw API reference:
|
|
87
|
+
|
|
88
|
+
```http
|
|
89
|
+
GET {DASHBOARD_URL}/api/workshop/instances
|
|
90
|
+
```
|
|
91
|
+
|
|
92
|
+
Rules:
|
|
93
|
+
- prefer this over inspecting local session files or composing one-off authenticated scripts
|
|
94
|
+
- use it when the facilitator needs to discover which live instances exist before reset, update, or scene work
|
|
95
|
+
- keep raw API usage as a diagnostic fallback, not the default operator workflow
|
|
96
|
+
|
|
97
|
+
### `/workshop facilitator show-instance <instance-id>`
|
|
98
|
+
|
|
99
|
+
Preferred path:
|
|
100
|
+
|
|
101
|
+
```bash
|
|
102
|
+
harness workshop show-instance sample-workshop-demo-orbit
|
|
103
|
+
```
|
|
104
|
+
|
|
105
|
+
Show:
|
|
106
|
+
- one explicit instance record
|
|
107
|
+
- summary metadata for quick operator inspection
|
|
108
|
+
- the full instance payload when the facilitator needs exact values before a mutation
|
|
109
|
+
|
|
110
|
+
Raw API reference:
|
|
111
|
+
|
|
112
|
+
```http
|
|
113
|
+
GET {DASHBOARD_URL}/api/workshop/instances/{instanceId}
|
|
114
|
+
```
|
|
115
|
+
|
|
116
|
+
Rules:
|
|
117
|
+
- use this when the facilitator needs one specific instance, not the deployment-default `workshop status`
|
|
118
|
+
- if the route returns `404`, the instance does not exist or is not visible to the facilitator
|
|
119
|
+
- prefer this over ad hoc authenticated scripts for routine discovery
|
|
120
|
+
|
|
68
121
|
### `/workshop facilitator grant <email> <role>`
|
|
69
122
|
|
|
70
123
|
Use the CLI-backed privileged request path. The skill should not handle auth bootstrap itself.
|
|
@@ -176,6 +229,7 @@ Rules:
|
|
|
176
229
|
- send only the fields you want to change
|
|
177
230
|
- do not use reset for an ordinary title, venue, or room correction
|
|
178
231
|
- if the route returns `400`, the payload is wrong; if it returns `404`, the instance does not exist
|
|
232
|
+
- use `--content-lang cs|en` when the facilitator intends to change the workshop delivery language for that instance
|
|
179
233
|
|
|
180
234
|
### `/workshop facilitator reset-instance <instance-id>`
|
|
181
235
|
|
package/package.json
CHANGED
package/src/client.js
CHANGED
|
@@ -90,6 +90,12 @@ export function createHarnessClient({ fetchFn, session }) {
|
|
|
90
90
|
getWorkshopStatus() {
|
|
91
91
|
return request("/api/workshop");
|
|
92
92
|
},
|
|
93
|
+
listWorkshopInstances() {
|
|
94
|
+
return request("/api/workshop/instances");
|
|
95
|
+
},
|
|
96
|
+
getWorkshopInstance(instanceId) {
|
|
97
|
+
return request(`/api/workshop/instances/${encodeURIComponent(instanceId)}`);
|
|
98
|
+
},
|
|
93
99
|
getAgenda() {
|
|
94
100
|
return request("/api/agenda");
|
|
95
101
|
},
|
package/src/run-cli.js
CHANGED
|
@@ -103,6 +103,7 @@ async function readRequiredCommandValue(io, flags, keys, promptLabel, fallbackVa
|
|
|
103
103
|
|
|
104
104
|
function buildWorkshopMetadataInput(flags) {
|
|
105
105
|
const input = {
|
|
106
|
+
contentLang: readStringFlag(flags, "content-lang", "content-language"),
|
|
106
107
|
eventTitle: readStringFlag(flags, "event-title", "title"),
|
|
107
108
|
city: readStringFlag(flags, "city"),
|
|
108
109
|
dateRange: readStringFlag(flags, "date-range", "date"),
|
|
@@ -122,6 +123,7 @@ function hasWorkshopMetadataInput(input) {
|
|
|
122
123
|
|
|
123
124
|
async function promptWorkshopMetadataInput(io) {
|
|
124
125
|
const prompts = [
|
|
126
|
+
["contentLang", "Content language (cs/en, leave blank to skip): "],
|
|
125
127
|
["eventTitle", "Event title (leave blank to skip): "],
|
|
126
128
|
["city", "City (leave blank to skip): "],
|
|
127
129
|
["dateRange", "Date range (leave blank to skip): "],
|
|
@@ -148,7 +150,9 @@ function summarizeWorkshopInstance(instance) {
|
|
|
148
150
|
|
|
149
151
|
return {
|
|
150
152
|
instanceId: instance?.id ?? null,
|
|
153
|
+
templateId: instance?.templateId ?? null,
|
|
151
154
|
status: instance?.status ?? null,
|
|
155
|
+
contentLang: workshopMeta.contentLang ?? null,
|
|
152
156
|
eventTitle: workshopMeta.eventTitle ?? null,
|
|
153
157
|
city: workshopMeta.city ?? null,
|
|
154
158
|
dateRange: workshopMeta.dateRange ?? null,
|
|
@@ -175,9 +179,11 @@ function printUsage(io, ui) {
|
|
|
175
179
|
"harness auth status",
|
|
176
180
|
"harness skill install [--target PATH] [--force]",
|
|
177
181
|
"harness workshop status",
|
|
182
|
+
"harness workshop list-instances",
|
|
183
|
+
"harness workshop show-instance <instance-id>",
|
|
178
184
|
"harness workshop archive [--notes TEXT]",
|
|
179
|
-
"harness workshop create-instance [<instance-id>] [--template-id ID] [--event-title TEXT] [--city CITY]",
|
|
180
|
-
"harness workshop update-instance <instance-id> [--event-title TEXT] [--city CITY]",
|
|
185
|
+
"harness workshop create-instance [<instance-id>] [--template-id ID] [--content-lang cs|en] [--event-title TEXT] [--city CITY]",
|
|
186
|
+
"harness workshop update-instance <instance-id> [--content-lang cs|en] [--event-title TEXT] [--city CITY]",
|
|
181
187
|
"harness workshop reset-instance <instance-id> [--template-id ID]",
|
|
182
188
|
"harness workshop prepare <instance-id>",
|
|
183
189
|
"harness workshop remove-instance <instance-id>",
|
|
@@ -583,6 +589,67 @@ async function handleWorkshopStatus(io, ui, env, deps) {
|
|
|
583
589
|
}
|
|
584
590
|
}
|
|
585
591
|
|
|
592
|
+
async function handleWorkshopListInstances(io, ui, env, deps) {
|
|
593
|
+
const session = await requireSession(io, ui, env);
|
|
594
|
+
if (!session) {
|
|
595
|
+
return 1;
|
|
596
|
+
}
|
|
597
|
+
|
|
598
|
+
try {
|
|
599
|
+
const client = createHarnessClient({ fetchFn: deps.fetchFn, session });
|
|
600
|
+
const result = await client.listWorkshopInstances();
|
|
601
|
+
const items = Array.isArray(result?.items) ? result.items.map((instance) => summarizeWorkshopInstance(instance)) : [];
|
|
602
|
+
ui.json("Workshop Instances", {
|
|
603
|
+
ok: true,
|
|
604
|
+
count: items.length,
|
|
605
|
+
items,
|
|
606
|
+
});
|
|
607
|
+
return 0;
|
|
608
|
+
} catch (error) {
|
|
609
|
+
if (error instanceof HarnessApiError) {
|
|
610
|
+
ui.status("error", `List instances failed: ${error.message}`, { stream: "stderr" });
|
|
611
|
+
return 1;
|
|
612
|
+
}
|
|
613
|
+
throw error;
|
|
614
|
+
}
|
|
615
|
+
}
|
|
616
|
+
|
|
617
|
+
async function handleWorkshopShowInstance(io, ui, env, positionals, flags, deps) {
|
|
618
|
+
const session = await requireSession(io, ui, env);
|
|
619
|
+
if (!session) {
|
|
620
|
+
return 1;
|
|
621
|
+
}
|
|
622
|
+
|
|
623
|
+
const instanceId = await readRequiredCommandValue(
|
|
624
|
+
io,
|
|
625
|
+
flags,
|
|
626
|
+
["id", "instance-id"],
|
|
627
|
+
"Instance id: ",
|
|
628
|
+
readOptionalPositional(positionals, 2),
|
|
629
|
+
);
|
|
630
|
+
if (!instanceId) {
|
|
631
|
+
ui.status("error", "Instance id is required.", { stream: "stderr" });
|
|
632
|
+
return 1;
|
|
633
|
+
}
|
|
634
|
+
|
|
635
|
+
try {
|
|
636
|
+
const client = createHarnessClient({ fetchFn: deps.fetchFn, session });
|
|
637
|
+
const result = await client.getWorkshopInstance(instanceId);
|
|
638
|
+
ui.json("Workshop Instance", {
|
|
639
|
+
ok: true,
|
|
640
|
+
...summarizeWorkshopInstance(result.instance),
|
|
641
|
+
instance: result.instance,
|
|
642
|
+
});
|
|
643
|
+
return 0;
|
|
644
|
+
} catch (error) {
|
|
645
|
+
if (error instanceof HarnessApiError) {
|
|
646
|
+
ui.status("error", `Show instance failed: ${error.message}`, { stream: "stderr" });
|
|
647
|
+
return 1;
|
|
648
|
+
}
|
|
649
|
+
throw error;
|
|
650
|
+
}
|
|
651
|
+
}
|
|
652
|
+
|
|
586
653
|
async function handleWorkshopArchive(io, ui, env, flags, deps) {
|
|
587
654
|
const session = await requireSession(io, ui, env);
|
|
588
655
|
if (!session) {
|
|
@@ -880,6 +947,14 @@ export async function runCli(argv, io, deps = {}) {
|
|
|
880
947
|
return handleWorkshopStatus(io, ui, io.env, mergedDeps);
|
|
881
948
|
}
|
|
882
949
|
|
|
950
|
+
if (scope === "workshop" && action === "list-instances") {
|
|
951
|
+
return handleWorkshopListInstances(io, ui, io.env, mergedDeps);
|
|
952
|
+
}
|
|
953
|
+
|
|
954
|
+
if (scope === "workshop" && action === "show-instance") {
|
|
955
|
+
return handleWorkshopShowInstance(io, ui, io.env, positionals, flags, mergedDeps);
|
|
956
|
+
}
|
|
957
|
+
|
|
883
958
|
if (scope === "workshop" && action === "archive") {
|
|
884
959
|
return handleWorkshopArchive(io, ui, io.env, flags, mergedDeps);
|
|
885
960
|
}
|