@mediamonks/canopy-cli 0.7.21 → 0.7.22
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/docs/index.json +20 -5
- package/dist/docs/platform-assistant.md +50 -0
- package/dist/docs/platform-feedback.md +3 -0
- package/dist/docs/{notifications.md → platform-notifications.md} +6 -2
- package/dist/docs/platform-slack.md +85 -0
- package/dist/docs/sdk-slack.md +132 -0
- package/dist/{docs-fiC6q9Ce.mjs → docs-c0CdeBxh.mjs} +1 -1
- package/dist/{feedback-CAwUHwWa.mjs → feedback-QhD8k6Ph.mjs} +8 -3
- package/dist/index.mjs +9 -9
- package/dist/login-BrEDKrb3.mjs +285 -0
- package/dist/{package-C_DLlB96.mjs → package-BuwV_mje.mjs} +1 -1
- package/dist/{skill-CmgMU2Iq.mjs → skill-BvoYCIKk.mjs} +1 -1
- package/dist/{upgrade-D1j0WV4l.mjs → upgrade-0lmdjvom.mjs} +1 -1
- package/dist/{usage-CRpVLLi6.mjs → usage-C1-cvS2-.mjs} +13 -1
- package/package.json +1 -1
- package/dist/login-DRYaJcfT.mjs +0 -285
package/dist/docs/index.json
CHANGED
|
@@ -77,11 +77,6 @@
|
|
|
77
77
|
"title": "CLI command reference",
|
|
78
78
|
"summary": "Every canopy command, its flags, and what it does."
|
|
79
79
|
},
|
|
80
|
-
{
|
|
81
|
-
"slug": "notifications",
|
|
82
|
-
"title": "Slack notifications",
|
|
83
|
-
"summary": "Canopy DMs you about your reports and projects — replies, new reports, blocked fetches, budget hits, failing schedules — and answers questions when you ask."
|
|
84
|
-
},
|
|
85
80
|
{
|
|
86
81
|
"slug": "static-serving",
|
|
87
82
|
"title": "How static files are served",
|
|
@@ -129,6 +124,11 @@
|
|
|
129
124
|
"title": "Google",
|
|
130
125
|
"summary": "Let your project work with Google data — Sheets, Docs, Calendar, Drive, Gmail — without handling any OAuth yourself."
|
|
131
126
|
},
|
|
127
|
+
{
|
|
128
|
+
"slug": "platform-slack",
|
|
129
|
+
"title": "Slack",
|
|
130
|
+
"summary": "Give your project its own Slack bot — Canopy creates and manages the app, your code handles the events."
|
|
131
|
+
},
|
|
132
132
|
{
|
|
133
133
|
"slug": "platform-members-and-access",
|
|
134
134
|
"title": "Members & access",
|
|
@@ -139,6 +139,16 @@
|
|
|
139
139
|
"title": "Feedback & bug reports",
|
|
140
140
|
"summary": "A built-in feedback widget on every project, a ticket-lite inbox behind it, and a CLI that lets agents work the backlog."
|
|
141
141
|
},
|
|
142
|
+
{
|
|
143
|
+
"slug": "platform-notifications",
|
|
144
|
+
"title": "Notifications",
|
|
145
|
+
"summary": "Canopy DMs you on Slack about your reports and projects — replies, new reports, blocked fetches, budget hits, failing schedules."
|
|
146
|
+
},
|
|
147
|
+
{
|
|
148
|
+
"slug": "platform-assistant",
|
|
149
|
+
"title": "The Canopy assistant",
|
|
150
|
+
"summary": "Ask questions about your projects and the platform in plain language — in Slack, or from the button in the corner of the docs and the dashboard."
|
|
151
|
+
},
|
|
142
152
|
{
|
|
143
153
|
"slug": "platform-client-access",
|
|
144
154
|
"title": "Client access",
|
|
@@ -323,6 +333,11 @@
|
|
|
323
333
|
"title": "Google",
|
|
324
334
|
"summary": "Call Google APIs as the project's connected account or as the visitor's own — the platform holds the OAuth."
|
|
325
335
|
},
|
|
336
|
+
{
|
|
337
|
+
"slug": "sdk-slack",
|
|
338
|
+
"title": "Slack",
|
|
339
|
+
"summary": "Handle your bot's events and slash commands in your worker, and post to Slack as the bot — no tokens in project code."
|
|
340
|
+
},
|
|
326
341
|
{
|
|
327
342
|
"slug": "sdk-services",
|
|
328
343
|
"title": "Services",
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: The Canopy assistant
|
|
3
|
+
description: Ask questions about your projects and the platform in plain language — in Slack, or from the button in the corner of the docs and the dashboard.
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
Canopy has an assistant that answers questions about **your projects** and
|
|
7
|
+
**how the platform works**. It reads the same things you can see — your
|
|
8
|
+
projects, their deploys, reports, AI spend, egress log and schedules — plus
|
|
9
|
+
these docs, and answers with a link to the guide it answered from.
|
|
10
|
+
|
|
11
|
+
It can only read. It never deploys, rolls back, changes settings or touches
|
|
12
|
+
your data; asked to, it points you at the dashboard or the `canopy` CLI.
|
|
13
|
+
|
|
14
|
+
## Where to ask
|
|
15
|
+
|
|
16
|
+
**In the docs and the dashboard.** The floating button in the bottom-right
|
|
17
|
+
corner opens a choice: send feedback, or ask the assistant. Pick the second
|
|
18
|
+
and type your question. The page you're on sets the context, so on a project's
|
|
19
|
+
dashboard page "how many deploys today?" already knows which project you mean.
|
|
20
|
+
|
|
21
|
+
Your conversation survives a reload — come back to the tab an hour later and
|
|
22
|
+
it's still there. **New chat** clears it and starts over. Only one
|
|
23
|
+
conversation is kept, and it lives in your own browser.
|
|
24
|
+
|
|
25
|
+
**In Slack.** DM **Canopy**, or mention **@Canopy** in a channel. Same
|
|
26
|
+
assistant, same answers. In a channel linked to a project it knows which
|
|
27
|
+
project you mean; replying in a report's notification thread, it knows which
|
|
28
|
+
report. See [Notifications](https://docs.canopy.website/platform/notifications).
|
|
29
|
+
|
|
30
|
+
## What it's good at
|
|
31
|
+
|
|
32
|
+
- **"Why is my fetch failing?"** — it checks the egress log and tells you
|
|
33
|
+
which host was blocked, and where to allow it.
|
|
34
|
+
- **"What happened on my project today?"** — deploys, new reports, status
|
|
35
|
+
changes.
|
|
36
|
+
- **"How do I promote staging to live?"** — it looks it up in these docs
|
|
37
|
+
rather than guessing.
|
|
38
|
+
- **"What's the context on this report?"** — the body, the trail, and the
|
|
39
|
+
triage notes you're allowed to see.
|
|
40
|
+
|
|
41
|
+
## What it can't do
|
|
42
|
+
|
|
43
|
+
- **Change anything.** Read-only, by design.
|
|
44
|
+
- **See projects you can't.** Every lookup runs as you: a project you're not
|
|
45
|
+
on simply doesn't resolve.
|
|
46
|
+
- **Answer questions about your app's own content.** It knows Canopy and your
|
|
47
|
+
projects on it — not what's inside them.
|
|
48
|
+
|
|
49
|
+
It runs on a small daily budget shared by everyone. On the rare day that runs
|
|
50
|
+
out, it says so and comes back the next.
|
|
@@ -18,6 +18,9 @@ boards.
|
|
|
18
18
|
|
|
19
19
|
- Appears only for **signed-in Monks**. Client-password visitors never see it —
|
|
20
20
|
the platform doesn't even send them the script.
|
|
21
|
+
- On Canopy's own pages (these docs and the dashboard) the same button also
|
|
22
|
+
opens [the assistant](https://docs.canopy.website/platform/assistant); on your project it is a feedback
|
|
23
|
+
widget and nothing else.
|
|
21
24
|
- On by default for every project. Turn it off per project in
|
|
22
25
|
**Settings → Feedback widget**; the change applies on the next page load.
|
|
23
26
|
- Submissions are always identified (your company sign-in), so there's no
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
---
|
|
2
|
-
title:
|
|
3
|
-
description: Canopy DMs you about your reports and projects — replies, new reports, blocked fetches, budget hits, failing schedules
|
|
2
|
+
title: Notifications
|
|
3
|
+
description: Canopy DMs you on Slack about your reports and projects — replies, new reports, blocked fetches, budget hits, failing schedules.
|
|
4
4
|
---
|
|
5
5
|
|
|
6
6
|
Canopy sends you Slack DMs when something on the platform needs your
|
|
@@ -51,6 +51,10 @@ for that it points you at the dashboard or the CLI. In a channel that's
|
|
|
51
51
|
linked to a project, it already knows which project you mean; replying in a
|
|
52
52
|
report's notification thread, it knows which report.
|
|
53
53
|
|
|
54
|
+
The same assistant answers from the button in the corner of these docs and
|
|
55
|
+
the dashboard, if you'd rather not switch to Slack — see
|
|
56
|
+
[The Canopy assistant](https://docs.canopy.website/platform/assistant).
|
|
57
|
+
|
|
54
58
|
## If DMs don't arrive
|
|
55
59
|
|
|
56
60
|
The bot finds you by your work email. If your Slack account uses a different
|
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: Slack
|
|
3
|
+
description: Give your project its own Slack bot — Canopy creates and manages the app, your code handles the events.
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
Your project can have its own Slack app: its own name and bot, in whatever
|
|
7
|
+
workspace you choose. Canopy creates the app, keeps its settings in sync,
|
|
8
|
+
holds every credential, and routes Slack's traffic to your backend. Your
|
|
9
|
+
code never sees a bot token, a signing secret, or a webhook — it exports a
|
|
10
|
+
handler and calls `canopy.slack`, both covered in
|
|
11
|
+
[the SDK reference](https://docs.canopy.website/sdk/slack).
|
|
12
|
+
|
|
13
|
+
Everything on this page happens on the project's **Services** tab.
|
|
14
|
+
|
|
15
|
+
## One-time: your configuration token
|
|
16
|
+
|
|
17
|
+
Creating Slack apps requires a Slack _app configuration token_, which is
|
|
18
|
+
personal — it belongs to you, in one workspace. You set it up once and every
|
|
19
|
+
project you manage shares it:
|
|
20
|
+
|
|
21
|
+
1. Go to [api.slack.com/apps](https://api.slack.com/apps) and pick the
|
|
22
|
+
workspace your bots should live in — **that choice is baked into the
|
|
23
|
+
token**, and it's where every app you create will land.
|
|
24
|
+
2. Under "Your App Configuration Tokens", generate a token and copy the
|
|
25
|
+
**refresh token** (the one starting `xoxe-1-`). The access token isn't
|
|
26
|
+
needed.
|
|
27
|
+
3. Paste it into the token section of any project's Services tab and save.
|
|
28
|
+
|
|
29
|
+
Canopy validates it against Slack, stores it encrypted, and keeps it fresh
|
|
30
|
+
from then on — this is genuinely one-time. If it ever stops working (for
|
|
31
|
+
example, it was revoked), existing bots keep running; only app-settings
|
|
32
|
+
changes pause until you paste a fresh one.
|
|
33
|
+
|
|
34
|
+
To create bots in a different workspace — a client's, say — generate a token
|
|
35
|
+
for that workspace and save it. One workspace at a time per person.
|
|
36
|
+
|
|
37
|
+
## Creating the app
|
|
38
|
+
|
|
39
|
+
Name the bot, pick its features, create. Every app comes with a bot that can
|
|
40
|
+
be invited to channels, post messages, and send people direct messages — the
|
|
41
|
+
notification baseline, no options needed. On top of that:
|
|
42
|
+
|
|
43
|
+
- **AI assistant** — people can chat with the bot: by @-mentioning it in
|
|
44
|
+
channels, in direct messages, and in Slack's assistant pane. Without it
|
|
45
|
+
the bot only sends; nobody can talk back. One caveat from Slack's side:
|
|
46
|
+
once on, it can't be turned off again.
|
|
47
|
+
- **Slash commands** — each becomes a workspace command handled by your
|
|
48
|
+
backend. Command names aren't reserved per app, so pick ones another app
|
|
49
|
+
in the workspace isn't already using.
|
|
50
|
+
|
|
51
|
+
## Installing to the workspace
|
|
52
|
+
|
|
53
|
+
Creating the app doesn't put it in the workspace — installing does, and
|
|
54
|
+
that's a human step by design: you approve the bot's permissions on Slack's
|
|
55
|
+
own screen. Click **Install to workspace** and follow it through.
|
|
56
|
+
|
|
57
|
+
If your workspace requires admin approval for new apps, the first attempt
|
|
58
|
+
becomes an approval request instead. Once the admin approves (Slack DMs you
|
|
59
|
+
about it), come back and click install again.
|
|
60
|
+
|
|
61
|
+
The same button reappears whenever you change features in a way that needs
|
|
62
|
+
new permissions — the card shows a clear warning when saved changes are
|
|
63
|
+
waiting on a reinstall. Feature changes that don't widen permissions apply
|
|
64
|
+
immediately.
|
|
65
|
+
|
|
66
|
+
## Day to day
|
|
67
|
+
|
|
68
|
+
- **The status line** shows where the app is installed and when Slack last
|
|
69
|
+
delivered something — the quickest "is it wired up" check.
|
|
70
|
+
- **Enabled** is the kill switch: off, Slack traffic is accepted and
|
|
71
|
+
dropped, nothing reaches your code, and outbound sends are refused. The
|
|
72
|
+
app stays installed; flip it back anytime.
|
|
73
|
+
- **Remove Slack app** deletes the app from the workspace too — bot,
|
|
74
|
+
commands, history access, all of it.
|
|
75
|
+
|
|
76
|
+
Every message your project sends through the bot is counted per day, so a
|
|
77
|
+
runaway loop is visible.
|
|
78
|
+
|
|
79
|
+
## Local development
|
|
80
|
+
|
|
81
|
+
Slack needs a public URL to deliver to, so `canopy dev` can't receive
|
|
82
|
+
events or commands. Test inbound handling on a deployed project — a scratch
|
|
83
|
+
project with a scratch bot works well — and unit-test your handler directly.
|
|
84
|
+
Outbound (`canopy.slack.api`) works from `canopy dev` like any other SDK
|
|
85
|
+
call.
|
|
@@ -0,0 +1,132 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: Slack
|
|
3
|
+
description: Handle your bot's events and slash commands in your worker, and post to Slack as the bot — no tokens in project code.
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
Once your project has a Slack app ([set up on the Services
|
|
7
|
+
tab](https://docs.canopy.website/platform/slack)), the integration is two halves: inbound events arrive
|
|
8
|
+
at a `slack()` export in your worker, and outbound calls go through
|
|
9
|
+
`canopy.slack`. The bot token and signing secret stay with the platform —
|
|
10
|
+
Slack's signatures are verified before anything reaches your code.
|
|
11
|
+
|
|
12
|
+
## The `slack()` handler
|
|
13
|
+
|
|
14
|
+
Export it next to `fetch` and `scheduled`:
|
|
15
|
+
|
|
16
|
+
```ts
|
|
17
|
+
export default {
|
|
18
|
+
fetch(request, env) {
|
|
19
|
+
/* … */
|
|
20
|
+
},
|
|
21
|
+
|
|
22
|
+
async slack(event, env) {
|
|
23
|
+
if (event.kind === "command") {
|
|
24
|
+
return { response_type: "in_channel", text: `Running ${event.payload.command}…` };
|
|
25
|
+
}
|
|
26
|
+
// kind === "event": an @-mention, a DM, …
|
|
27
|
+
},
|
|
28
|
+
};
|
|
29
|
+
```
|
|
30
|
+
|
|
31
|
+
**The event object:**
|
|
32
|
+
|
|
33
|
+
- `kind` — `"event"` (Events API: `app_mention`, `message`, …) or
|
|
34
|
+
`"command"` (a slash command).
|
|
35
|
+
- `payload` — Slack's payload, verbatim. For events that's the full
|
|
36
|
+
callback (the interesting part is `payload.event`); for commands it's the
|
|
37
|
+
command form fields (`command`, `text`, `channel_id`, `user_id`, …).
|
|
38
|
+
- `responseUrl` — commands only: where a late reply can still be sent (see
|
|
39
|
+
below).
|
|
40
|
+
- `user` — who triggered this, as Slack tells it: `{ id, name? }`. Present
|
|
41
|
+
whenever Slack names a person.
|
|
42
|
+
- `teamId`, `appId` — which workspace and app this came from.
|
|
43
|
+
- `retry` — set when Slack is redelivering. Delivery is at-least-once, so
|
|
44
|
+
handlers that create things should tolerate seeing an event twice.
|
|
45
|
+
|
|
46
|
+
## Who is talking to the bot
|
|
47
|
+
|
|
48
|
+
Two identities, at two trust levels:
|
|
49
|
+
|
|
50
|
+
- **`env.USER`** is set when the bot lives in the Monks workspace and the
|
|
51
|
+
sender has a Canopy account: the same `{ sub, email, name }` your fetch
|
|
52
|
+
routes see for a signed-in visitor, so user-specific logic works the same
|
|
53
|
+
way. The mapping rides the corporate directory — Slack accounts and Canopy
|
|
54
|
+
sign-ins are the same people there.
|
|
55
|
+
- In any other workspace — a client's, say — `env.USER` is `null` and
|
|
56
|
+
`event.user` is all you get: Slack's own word for who typed, nothing
|
|
57
|
+
Canopy has verified. Fine for personalising a reply; don't hang
|
|
58
|
+
authorization on it.
|
|
59
|
+
|
|
60
|
+
Either way, payload text is written by whoever typed it in Slack — treat it
|
|
61
|
+
as untrusted input. And SDK calls from the handler still run as the project
|
|
62
|
+
itself (`canopy.auth.user()` reports kind `worker`), regardless of
|
|
63
|
+
`env.USER`.
|
|
64
|
+
|
|
65
|
+
## Answering a slash command
|
|
66
|
+
|
|
67
|
+
Slack gives a command three seconds. Return quickly and Canopy relays your
|
|
68
|
+
answer as the command's response:
|
|
69
|
+
|
|
70
|
+
```ts
|
|
71
|
+
async slack(event, env) {
|
|
72
|
+
if (event.kind === "command") {
|
|
73
|
+
return { response_type: "ephemeral", text: "Done." };
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
```
|
|
77
|
+
|
|
78
|
+
Return a Slack message object, or a plain string (sent as ephemeral text).
|
|
79
|
+
Return nothing and the command completes silently.
|
|
80
|
+
|
|
81
|
+
If your handler needs longer — it queries something slow, calls a model —
|
|
82
|
+
the command is acknowledged for you, and you answer afterwards through the
|
|
83
|
+
`responseUrl`, which stays valid for 30 minutes:
|
|
84
|
+
|
|
85
|
+
```ts
|
|
86
|
+
if (event.kind === "command") {
|
|
87
|
+
const answer = await somethingSlow();
|
|
88
|
+
await canopy.slack.respond(event.responseUrl!, {
|
|
89
|
+
response_type: "in_channel",
|
|
90
|
+
text: answer,
|
|
91
|
+
});
|
|
92
|
+
}
|
|
93
|
+
```
|
|
94
|
+
|
|
95
|
+
Events (`kind: "event"`) have no response channel — react by calling out,
|
|
96
|
+
usually `chat.postMessage` back into the conversation the event names.
|
|
97
|
+
|
|
98
|
+
## slack.api(method, args)
|
|
99
|
+
|
|
100
|
+
Any [Slack Web API method](https://docs.slack.dev/reference/methods), called
|
|
101
|
+
as your project's bot:
|
|
102
|
+
|
|
103
|
+
```ts
|
|
104
|
+
const result = await canopy.slack.api("chat.postMessage", {
|
|
105
|
+
channel: "C0123456789",
|
|
106
|
+
text: "Deploy finished.",
|
|
107
|
+
});
|
|
108
|
+
if (!result.ok) console.warn("slack said no:", result.error);
|
|
109
|
+
```
|
|
110
|
+
|
|
111
|
+
The response is Slack's own, `ok: false` included — check it for
|
|
112
|
+
method-level outcomes like `channel_not_found` or `not_in_channel` (the bot
|
|
113
|
+
can only post to channels it's been invited to, and to people's DMs).
|
|
114
|
+
Workspace-management method families (`admin.*`, `tooling.*`, `apps.*`,
|
|
115
|
+
`oauth.*`) are refused before Slack is ever contacted; everything else is
|
|
116
|
+
bounded by the permissions the app was installed with.
|
|
117
|
+
|
|
118
|
+
Backend and `canopy dev` only — pages can't call it, so a visitor can never
|
|
119
|
+
act as your bot.
|
|
120
|
+
|
|
121
|
+
## slack.respond(responseUrl, message)
|
|
122
|
+
|
|
123
|
+
The late reply to a slash command, described above. `message` is a Slack
|
|
124
|
+
message object or a plain string.
|
|
125
|
+
|
|
126
|
+
## Errors
|
|
127
|
+
|
|
128
|
+
Refusals arrive as thrown errors with stable codes: `slack_not_configured`
|
|
129
|
+
(no app on this project), `slack_not_installed` (created but not installed
|
|
130
|
+
to a workspace), `slack_disabled` (switched off on the Services tab), and
|
|
131
|
+
`slack_method_not_allowed`. A network-level failure reaching Slack is
|
|
132
|
+
`slack_api_error`.
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { t as version } from "./package-
|
|
1
|
+
import { t as version } from "./package-BuwV_mje.mjs";
|
|
2
2
|
import { n as siteConfig } from "./site-BFaWfSVu.mjs";
|
|
3
3
|
import { i as latestKnownVersion, r as compareSemver } from "./version-check-CcsA1QjI.mjs";
|
|
4
4
|
import { r as reportErrors } from "./ui--atbZ-TM.mjs";
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { t as version } from "./package-
|
|
1
|
+
import { t as version } from "./package-BuwV_mje.mjs";
|
|
2
2
|
import { a as projectDirArgs, c as resolveProject, d as tryResolveProject, n as siteConfig, u as tryReadCanopyJson } from "./site-BFaWfSVu.mjs";
|
|
3
3
|
import { c as apiDownload, l as apiRequest, r as reportErrors, t as formatDateTime, u as apiUpload } from "./ui--atbZ-TM.mjs";
|
|
4
4
|
import { defineCommand } from "citty";
|
|
@@ -89,6 +89,10 @@ function firstLine(body) {
|
|
|
89
89
|
const line = body.split("\n")[0] ?? "";
|
|
90
90
|
return line.length > 72 ? `${line.slice(0, 71)}…` : line;
|
|
91
91
|
}
|
|
92
|
+
/** List label: the AI-written title when there is one, else the first line. */
|
|
93
|
+
function itemLabel(item) {
|
|
94
|
+
return firstLine(item.title || item.body);
|
|
95
|
+
}
|
|
92
96
|
function printItems(items) {
|
|
93
97
|
if (items.length === 0) {
|
|
94
98
|
console.log("No matching feedback items.");
|
|
@@ -97,7 +101,7 @@ function printItems(items) {
|
|
|
97
101
|
for (const item of items) {
|
|
98
102
|
const comments = item.comment_count ? ` 💬${item.comment_count}` : "";
|
|
99
103
|
const shots = item.attachment_count ? ` 📎${item.attachment_count}` : "";
|
|
100
|
-
console.log(`${item.id} ${item.status} ${item.kind} ${
|
|
104
|
+
console.log(`${item.id} ${item.status} ${item.kind} ${itemLabel(item)}${comments}${shots}`);
|
|
101
105
|
}
|
|
102
106
|
}
|
|
103
107
|
const listCommand = defineCommand({
|
|
@@ -153,6 +157,7 @@ const showCommand = defineCommand({
|
|
|
153
157
|
return;
|
|
154
158
|
}
|
|
155
159
|
const { item, comments } = detail;
|
|
160
|
+
if (item.title) console.log(item.title);
|
|
156
161
|
console.log(`${item.kind} · ${item.status} · via ${item.source} · ${formatDateTime(item.created_at)}`);
|
|
157
162
|
console.log(`reported by ${item.reporter_name || item.reporter_email || "unknown"}` + (item.deployment_id ? ` on ${item.deployment_id}` : "") + (item.channel === "staging" ? " (staging)" : ""));
|
|
158
163
|
console.log(`\n${item.body}\n`);
|
|
@@ -276,7 +281,7 @@ const mineCommand = defineCommand({
|
|
|
276
281
|
console.log("You haven't filed any reports.");
|
|
277
282
|
return;
|
|
278
283
|
}
|
|
279
|
-
for (const item of items) console.log(`${item.id} ${item.status} ${item.kind} [${item.project_slug}] ${
|
|
284
|
+
for (const item of items) console.log(`${item.id} ${item.status} ${item.kind} [${item.project_slug}] ${itemLabel(item)}`);
|
|
280
285
|
})
|
|
281
286
|
});
|
|
282
287
|
const reportCommand = defineCommand({
|
package/dist/index.mjs
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
import { t as version } from "./package-
|
|
2
|
+
import { t as version } from "./package-BuwV_mje.mjs";
|
|
3
3
|
import { r as siteHeaderLine, t as setInvocationProfile } from "./site-BFaWfSVu.mjs";
|
|
4
4
|
import { a as notifyOfUpdate, o as runRefresh } from "./version-check-CcsA1QjI.mjs";
|
|
5
5
|
import { defineCommand, runMain } from "citty";
|
|
@@ -60,9 +60,9 @@ const main = defineCommand({
|
|
|
60
60
|
description: "canopy — create and deploy vibecoded projects"
|
|
61
61
|
},
|
|
62
62
|
subCommands: {
|
|
63
|
-
login: () => import("./login-
|
|
64
|
-
whoami: () => import("./login-
|
|
65
|
-
logout: () => import("./login-
|
|
63
|
+
login: () => import("./login-BrEDKrb3.mjs").then((m) => m.loginCommand),
|
|
64
|
+
whoami: () => import("./login-BrEDKrb3.mjs").then((m) => m.whoamiCommand),
|
|
65
|
+
logout: () => import("./login-BrEDKrb3.mjs").then((m) => m.logoutCommand),
|
|
66
66
|
create: () => import("./projects-1r5387ui.mjs").then((m) => m.createCommand),
|
|
67
67
|
init: () => import("./projects-1r5387ui.mjs").then((m) => m.initCommand),
|
|
68
68
|
projects: () => import("./projects-1r5387ui.mjs").then((m) => m.projectsCommand),
|
|
@@ -76,13 +76,13 @@ const main = defineCommand({
|
|
|
76
76
|
token: () => import("./token-C8Bmzwfl.mjs").then((m) => m.tokenCommand),
|
|
77
77
|
egress: () => import("./egress-BhbQfjjV.mjs").then((m) => m.egressCommand),
|
|
78
78
|
schedule: () => import("./schedule-DK_Cv6Xf.mjs").then((m) => m.scheduleCommand),
|
|
79
|
-
feedback: () => import("./feedback-
|
|
79
|
+
feedback: () => import("./feedback-QhD8k6Ph.mjs").then((m) => m.feedbackCommand),
|
|
80
80
|
db: () => import("./db-TaSLpQZ5.mjs").then((m) => m.dbCommand),
|
|
81
|
-
usage: () => import("./usage-
|
|
81
|
+
usage: () => import("./usage-C1-cvS2-.mjs").then((m) => m.usageCommand),
|
|
82
82
|
open: () => import("./open-D7f1wNn3.mjs").then((m) => m.openCommand),
|
|
83
|
-
docs: () => import("./docs-
|
|
84
|
-
skill: () => import("./skill-
|
|
85
|
-
upgrade: () => import("./upgrade-
|
|
83
|
+
docs: () => import("./docs-c0CdeBxh.mjs").then((m) => m.docsCommand),
|
|
84
|
+
skill: () => import("./skill-BvoYCIKk.mjs").then((m) => m.skillCommand),
|
|
85
|
+
upgrade: () => import("./upgrade-0lmdjvom.mjs").then((m) => m.upgradeCommand),
|
|
86
86
|
logs: () => import("./logs-Beqz--Df.mjs").then((m) => m.logsCommand)
|
|
87
87
|
}
|
|
88
88
|
});
|