@dosu/cli 0.58.0 → 0.59.0
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 +8 -2
- package/bin/dosu.js +1175 -356
- package/package.json +2 -1
package/bin/dosu.js
CHANGED
|
@@ -1083,7 +1083,7 @@ function isNpxInvocation(channel = INSTALL_CHANNEL, env = process.env) {
|
|
|
1083
1083
|
function getVersionString() {
|
|
1084
1084
|
return `v${VERSION}`;
|
|
1085
1085
|
}
|
|
1086
|
-
var VERSION = "0.
|
|
1086
|
+
var VERSION = "0.59.0", INSTALL_CHANNEL = "npm";
|
|
1087
1087
|
|
|
1088
1088
|
// src/debug/logger.ts
|
|
1089
1089
|
import {
|
|
@@ -13742,7 +13742,7 @@ var init_sync = __esm(() => {
|
|
|
13742
13742
|
});
|
|
13743
13743
|
|
|
13744
13744
|
// src/telemetry/debug-id.ts
|
|
13745
|
-
var BUNDLE_DEBUG_ID_PLACEHOLDER = "
|
|
13745
|
+
var BUNDLE_DEBUG_ID_PLACEHOLDER = "ecb91fd5-693a-ffc0-6475-6e2164756e21";
|
|
13746
13746
|
|
|
13747
13747
|
// src/telemetry/telemetry.ts
|
|
13748
13748
|
import { randomUUID as randomUUID2 } from "node:crypto";
|
|
@@ -59799,255 +59799,1036 @@ var init_review = __esm(() => {
|
|
|
59799
59799
|
import_picocolors25 = __toESM(require_picocolors(), 1);
|
|
59800
59800
|
});
|
|
59801
59801
|
|
|
59802
|
-
// src/
|
|
59803
|
-
|
|
59804
|
-
|
|
59805
|
-
|
|
59806
|
-
|
|
59802
|
+
// src/generated/skills.ts
|
|
59803
|
+
var BUNDLED_SKILLS;
|
|
59804
|
+
var init_skills = __esm(() => {
|
|
59805
|
+
BUNDLED_SKILLS = [
|
|
59806
|
+
{
|
|
59807
|
+
name: "dosu",
|
|
59808
|
+
files: [
|
|
59809
|
+
{
|
|
59810
|
+
path: "SKILL.md",
|
|
59811
|
+
content: "---\nname: dosu\ndescription: 'Use the Dosu CLI to authenticate and configure coding agents; manage Libraries, Agents, sources, Monitor, documents, reviews, threads, topics, members, integrations, and deployments; query knowledge; or audit a repository for Dosu-generated docs. Use for Dosu platform work that should be done from a terminal instead of the web app.'\n---\n\n# Use the Dosu CLI\n\nOperate Dosu through `dosu`. Prefer structured output and let the CLI and App validate product rules.\n\n## Start correctly\n\n1. Run `dosu --version`. Do not probe installation with unrelated package-manager commands.\n2. If it is unavailable and Node is present, try `npx -y @dosu/cli --version` and use `npx -y @dosu/cli` as the command prefix for this session. Otherwise ask before installing anything.\n3. Run `dosu --help` or the relevant nested `--help` before using a command not covered by [the command reference](references/commands.md).\n4. Pass `--json` whenever that leaf command exposes it. Parse the result; do not scrape the human table.\n\n## Satisfy the right prerequisite\n\n- `dosu login` supplies the JWT used by tRPC-backed commands.\n- `dosu setup` selects an organization, Library context, and MCP deployment, creates an API key, and can configure an agent tool.\n- `dosu ask` needs an API key. `docs generate`, `docs auto-tag`, and `docs publish` need both JWT login and the API key. Other platform commands generally need JWT login; commands scoped to an organization or current Library also need the corresponding setup selection.\n- For coding-agent setup, follow the nonblocking `dosu setup --agent --tool <id>` workflow in [workflows.md](references/workflows.md). Relay its URL and execute its returned `resume_command`; never invent ticket commands.\n\n## Use current product terms\n\n- **Organization** is the account and permission boundary.\n- **Library** is the knowledge container shown in the App. Older APIs may call it a `space`; do not present that internal name to users.\n- **Data source** is an organization-level connection such as a repository, Slack channel, or Notion workspace. A Library can use already-connected sources.\n- **Agent** is a configurable GitHub, GitLab, Slack, or Teams deployment serving exactly one Library.\n- **Monitor** is per Library and source. It supports GitHub, GitLab, and Azure DevOps sources.\n- `dosu deployments` manages selectable **MCP deployments**. Do not use it as an Agent CRUD command.\n\n## Route by intent\n\n| Intent | Route |\n|---|---|\n| Set up Dosu end-to-end (\"set up dosu\", new Library from scratch) | Read the guided onboarding flow in [workflows.md](references/workflows.md) first; it is checkpoint-driven — ask, wait, then act |\n| Create or configure a Library | `dosu libraries ...` |\n| Attach existing organization sources | `dosu sources list` → `dosu libraries sources attach` |\n| Create or configure an Agent | `dosu agents ...` |\n| Ask for a synthesized answer | `dosu ask` |\n| Find source documents | `dosu knowledge search`, then `dosu docs get` |\n| Create, import, or publish docs | `dosu docs ...` |\n| Review a pending doc change or draft reply | Read [review-workflow.md](references/review-workflow.md) first |\n| Inspect conversations | `dosu threads ...` |\n| Browse managed topics | `dosu topics ...` |\n| Audit agent docs, README, architecture, or dependencies | Read [audit.md](references/audit.md) first |\n\nUse [commands.md](references/commands.md) as the sole detailed command and flag reference. Use [workflows.md](references/workflows.md) only for multi-command composition.\n\n## Apply Library and Agent semantics\n\n- To assemble a Library, list organization sources, create the Library, attach the chosen source IDs, then verify with `libraries info` and `libraries sources list`. The CLI cannot establish a brand-new OAuth connection.\n- `libraries sources config` resolves the provider on the App side. Read the command reference before choosing provider-specific options.\n- When creating a Library with a GitHub repository, or newly attaching one to an existing Library, treat Monitor as part of that setup unless the user opts out. Enable it with the whole-repository and `emoji` defaults, verify it, and explain that Monitor reviews pull requests to keep the Library's knowledge up to date. Follow [the Library workflow](references/workflows.md); do not ask the user to choose defaults.\n- Create an Agent from an existing source ID and let the App choose its defaults; do not synthesize config in shell commands. Each data source can back at most one Agent: a `CONFLICT` (409) from `agents create` means the source already has one — offer a different source or an authorized `agents move` instead of retrying.\n- Read Agent config before changing one existing leaf. Values are JSON. If a concurrent write returns `CONFLICT`, read again, re-evaluate the requested change, and retry only if it is still correct.\n- Moving an Agent replaces its Library. Verify the returned `space_id`; do not infer migration behavior for historical data from the move receipt.\n\n## Respect write boundaries\n\n- Treat an explicit, unambiguous user request for the exact mutation as authorization. Otherwise show the intended change and wait for confirmation.\n- For commands exposing `--confirm`, omit it first when a preview is useful; `{ \"confirmRequired\": true, \"applied\": false }` means nothing changed. Pass `--confirm` only after authorization.\n- Never batch-approve or batch-reject review items. Diff one item, explain it, and decide only the ID the user authorized.\n- Before deleting a Library, Agent, source, or document, state the exact target and impact. Before detaching a source, read and state the impact documented in the command reference. Some older delete commands do not enforce `--confirm`; the absence of a CLI prompt is not user approval.\n- Before attaching a source to a public Library, warn that its content becomes available to everyone who can access that Library.\n- OAuth connection and billing remain web-only. Report the boundary instead of claiming success.\n\n## Handle failures literally\n\n- `Not logged in` or an unrecoverable expired session: run `dosu login` (agent setup may instead return a ticket flow).\n- Missing organization, Library, deployment, or API-key context: run the appropriate `dosu setup` flow.\n- `confirmRequired`: no write occurred.\n- `CONFLICT` on config: reread before retrying.\n- A tRPC or backend error is a failed operation. Surface the code/path/status and do not imply the requested state exists.\n\n## References\n\n- [commands.md](references/commands.md): authoritative CLI syntax, choices, defaults, conflicts, and prerequisites\n- [workflows.md](references/workflows.md): reusable multi-command flows\n- [review-workflow.md](references/review-workflow.md): review safety and context\n- [audit.md](references/audit.md): repository audit procedure\n- [audit-findings-schema.md](references/audit-findings-schema.md): `.dosu/audit.json` contract\n",
|
|
59812
|
+
executable: false
|
|
59813
|
+
},
|
|
59814
|
+
{
|
|
59815
|
+
path: "references/audit-findings-schema.md",
|
|
59816
|
+
content: `# \`.dosu/audit.json\` — audit findings schema
|
|
59817
|
+
|
|
59818
|
+
The codebase audit (see [audit.md](audit.md)) writes its result to \`.dosu/audit.json\` at the
|
|
59819
|
+
repo root. This file is the contract between the audit you run in the coding agent and the
|
|
59820
|
+
\`dosu audit\` CLI command, which reads it, asks the user which docs to generate, and kicks off
|
|
59821
|
+
generation on Dosu cloud.
|
|
59822
|
+
|
|
59823
|
+
Write valid JSON matching this shape exactly. Do not add fields the CLI doesn't expect.
|
|
59824
|
+
|
|
59825
|
+
\`\`\`json
|
|
59826
|
+
{
|
|
59827
|
+
"version": 1,
|
|
59828
|
+
"generated_at": "2026-06-24T12:00:00Z",
|
|
59829
|
+
"repo": {
|
|
59830
|
+
"remote": "git@github.com:org/repo.git",
|
|
59831
|
+
"slug": "org/repo"
|
|
59832
|
+
},
|
|
59833
|
+
"items": [
|
|
59834
|
+
{
|
|
59835
|
+
"task": "generate-agents-md",
|
|
59836
|
+
"type": "agents",
|
|
59837
|
+
"file": "AGENTS.md",
|
|
59838
|
+
"status": "missing",
|
|
59839
|
+
"action": "create",
|
|
59840
|
+
"can_help": true,
|
|
59841
|
+
"confidence": "high",
|
|
59842
|
+
"rationale": "No AGENTS.md found; the repo has a clear src/ layout, a documented test command, and commit conventions worth capturing for agents.",
|
|
59843
|
+
"evidence": ["package.json", "src/cli/cli.ts", "CONTRIBUTING.md"]
|
|
59844
|
+
}
|
|
59845
|
+
]
|
|
59846
|
+
}
|
|
59847
|
+
\`\`\`
|
|
59848
|
+
|
|
59849
|
+
## Top-level fields
|
|
59850
|
+
|
|
59851
|
+
| Field | Type | Notes |
|
|
59852
|
+
|---|---|---|
|
|
59853
|
+
| \`version\` | number | Always \`1\`. The CLI rejects other versions. |
|
|
59854
|
+
| \`generated_at\` | string | ISO 8601 timestamp of when the audit ran. |
|
|
59855
|
+
| \`repo.remote\` | string | The \`git remote origin\` URL, verbatim. |
|
|
59856
|
+
| \`repo.slug\` | string | \`owner/name\` parsed from the remote (e.g. \`dosu-ai/dosu-cli\`). |
|
|
59857
|
+
| \`items\` | array | One entry per doc type you assessed. Include an entry for every type you looked at, even when \`can_help\` is \`false\` — the CLI uses these to explain what it skipped. |
|
|
59858
|
+
|
|
59859
|
+
## Item fields
|
|
59860
|
+
|
|
59861
|
+
| Field | Type | Allowed values | Notes |
|
|
59862
|
+
|---|---|---|---|
|
|
59863
|
+
| \`task\` | string | \`generate-agents-md\`, \`refresh-readme\`, \`generate-architecture-md\`, \`generate-deps-md\` | The backend capability id this item maps to. Must be one of these exact strings. |
|
|
59864
|
+
| \`type\` | string | \`agents\`, \`readme\`, \`architecture\`, \`deps\` | Short doc-type key. |
|
|
59865
|
+
| \`file\` | string | — | The target filename in the repo (e.g. \`AGENTS.md\`, \`README.md\`, \`architecture.md\`, \`deps.md\`). Use the casing already present in the repo when updating an existing file. |
|
|
59866
|
+
| \`status\` | string | \`missing\`, \`outdated\`, \`present_ok\` | What you found in the working tree. |
|
|
59867
|
+
| \`action\` | string | \`create\`, \`update\`, \`skip\` | What Dosu should do. \`create\` when \`missing\`; \`update\` when \`outdated\`; \`skip\` when \`present_ok\` (or when not enough info). |
|
|
59868
|
+
| \`can_help\` | boolean | — | Whether Dosu should offer this. \`false\` ⇒ the CLI shows it as not recommended (or omits it). |
|
|
59869
|
+
| \`confidence\` | string | \`high\`, \`medium\`, \`low\` | Your confidence in the recommendation. |
|
|
59870
|
+
| \`rationale\` | string | — | One or two sentences explaining the recommendation, citing what you saw. This is passed to Dosu cloud as generation guidance, so make it specific. |
|
|
59871
|
+
| \`evidence\` | string[] | — | Repo-relative paths (and optionally \`path:line\`) that justify the finding. |
|
|
59872
|
+
|
|
59873
|
+
## Mapping of \`task\` ↔ \`type\` ↔ \`file\`
|
|
59874
|
+
|
|
59875
|
+
| \`task\` | \`type\` | typical \`file\` |
|
|
59876
|
+
|---|---|---|
|
|
59877
|
+
| \`generate-agents-md\` | \`agents\` | \`AGENTS.md\` |
|
|
59878
|
+
| \`refresh-readme\` | \`readme\` | \`README.md\` |
|
|
59879
|
+
| \`generate-architecture-md\` | \`architecture\` | \`architecture.md\` |
|
|
59880
|
+
| \`generate-deps-md\` | \`deps\` | \`deps.md\` |
|
|
59881
|
+
`,
|
|
59882
|
+
executable: false
|
|
59883
|
+
},
|
|
59884
|
+
{
|
|
59885
|
+
path: "references/audit.md",
|
|
59886
|
+
content: `# Dosu codebase audit
|
|
59887
|
+
|
|
59888
|
+
This is the full procedure for the **codebase audit** referenced from [../SKILL.md](../SKILL.md).
|
|
59889
|
+
The goal: inspect the current repository and decide, with evidence, whether Dosu can help the
|
|
59890
|
+
user by creating or refreshing four docs. Write the result to \`.dosu/audit.json\`
|
|
59891
|
+
(see [audit-findings-schema.md](audit-findings-schema.md)), then tell the user to run
|
|
59892
|
+
\`dosu audit\` so the Dosu CLI can ask them which docs to generate and open a PR.
|
|
59893
|
+
|
|
59894
|
+
You (the coding agent) only do the **triage** here — you have the live working tree, so you can
|
|
59895
|
+
tell what exists, what's stale, and whether there's enough signal. You do **not** write the docs
|
|
59896
|
+
themselves; Dosu cloud generates them and opens the PR after the user picks via \`dosu audit\`.
|
|
59897
|
+
|
|
59898
|
+
## When to run this
|
|
59899
|
+
|
|
59900
|
+
Run when the user asks Dosu to audit the repo, asks "what can Dosu do for this codebase?", or
|
|
59901
|
+
asks to set up / refresh their agent docs, README, architecture doc, or dependency doc.
|
|
59902
|
+
|
|
59903
|
+
## The four doc types
|
|
59904
|
+
|
|
59905
|
+
| \`task\` | File | When Dosu can help |
|
|
59906
|
+
|---|---|---|
|
|
59907
|
+
| \`generate-agents-md\` | \`AGENTS.md\` | Missing, or present but stale/thin given the repo's structure, commands, and conventions. |
|
|
59908
|
+
| \`refresh-readme\` | \`README.md\` | Present but **outdated** — references removed scripts/deps, missing setup steps, or describes features that no longer match the code. |
|
|
59909
|
+
| \`generate-architecture-md\` | \`architecture.md\` | **Missing AND** there is genuinely enough structure to describe (multiple modules/services, clear layering). Do not recommend for a tiny or single-file repo. |
|
|
59910
|
+
| \`generate-deps-md\` | \`deps.md\` | Missing, or present but out of sync with the actual dependency manifests. |
|
|
59911
|
+
|
|
59912
|
+
## Rules
|
|
59913
|
+
|
|
59914
|
+
- **Be evidence-based.** Prefer direct repo evidence over inference. Cite concrete \`evidence\`:
|
|
59915
|
+
file paths (and \`path:line\` where useful), manifest entries, config keys.
|
|
59916
|
+
- **Gate \`architecture.md\` strictly.** Only set \`can_help: true\` for \`generate-architecture-md\`
|
|
59917
|
+
when the repo is large/structured enough that a useful architecture doc can be written. When in
|
|
59918
|
+
doubt, set \`can_help: false\`, \`action: "skip"\`, and a \`rationale\` saying why.
|
|
59919
|
+
- **Distinguish status from action.** \`status\` is what you found (\`missing\` / \`outdated\` /
|
|
59920
|
+
\`present_ok\`); \`action\` is what Dosu should do (\`create\` / \`update\` / \`skip\`).
|
|
59921
|
+
- **Include every type you assessed**, even when \`can_help\` is \`false\`, so the CLI can explain
|
|
59922
|
+
what it skipped and why.
|
|
59923
|
+
- **Make \`rationale\` specific** — it is forwarded to Dosu cloud as generation guidance. "README's
|
|
59924
|
+
install section references a \`make bootstrap\` target that no longer exists" beats "README looks
|
|
59925
|
+
old."
|
|
59926
|
+
- **Don't write the docs.** Producing the actual files is Dosu cloud's job, triggered by the user
|
|
59927
|
+
through \`dosu audit\`.
|
|
59928
|
+
|
|
59929
|
+
## Use Dosu MCP for org knowledge
|
|
59930
|
+
|
|
59931
|
+
Before finalizing recommendations, use the Dosu MCP tools to pull organization knowledge that
|
|
59932
|
+
should inform the docs (architecture decisions, naming, conventions, prior docs). The exposed
|
|
59933
|
+
tool set depends on the connection — always use what's actually listed:
|
|
59934
|
+
|
|
59935
|
+
1. Read first: call \`read_knowledge\` when listed (or \`init_knowledge\` on older connections) to
|
|
59936
|
+
get task-relevant context from the knowledge base.
|
|
59937
|
+
2. Go deeper with whichever search/ask tools the server exposes — check whether the org already
|
|
59938
|
+
documents the architecture, dependencies, or agent conventions elsewhere. If it does, factor
|
|
59939
|
+
that into \`status\`/\`rationale\` (e.g. an existing architecture doc in Dosu may mean a repo
|
|
59940
|
+
\`architecture.md\` should mirror it).
|
|
59941
|
+
|
|
59942
|
+
If no Dosu deployment is connected (only public-library tools are available), skip the MCP step
|
|
59943
|
+
and rely on repo evidence alone; note in the \`rationale\` that org knowledge wasn't consulted.
|
|
59944
|
+
|
|
59945
|
+
## Procedure
|
|
59946
|
+
|
|
59947
|
+
1. **Identify the repo.** Get the remote and slug:
|
|
59948
|
+
\`\`\`bash
|
|
59949
|
+
git config --get remote.origin.url
|
|
59950
|
+
\`\`\`
|
|
59951
|
+
Parse \`owner/name\` from it for \`repo.slug\`. If there is no GitHub remote, tell the user the
|
|
59952
|
+
audit needs a GitHub repo connected to Dosu and stop.
|
|
59953
|
+
|
|
59954
|
+
2. **Inspect the working tree** for each doc type. Useful starting points:
|
|
59955
|
+
\`\`\`bash
|
|
59956
|
+
ls -a
|
|
59957
|
+
# existing docs (any casing)
|
|
59958
|
+
ls AGENTS.md README.md architecture.md ARCHITECTURE.md deps.md DEPS.md docs/ 2>/dev/null
|
|
59959
|
+
# dependency manifests
|
|
59960
|
+
ls package.json pyproject.toml requirements*.txt go.mod Cargo.toml Gemfile pom.xml build.gradle 2>/dev/null
|
|
59961
|
+
\`\`\`
|
|
59962
|
+
- **AGENTS.md** — does it exist? If yes, is it consistent with the current build/test commands,
|
|
59963
|
+
directory layout, and contribution conventions? Read it and compare against \`package.json\`
|
|
59964
|
+
scripts / Makefile / CI config.
|
|
59965
|
+
- **README.md** — read it. Are the setup/build/run steps still accurate? Do referenced scripts,
|
|
59966
|
+
commands, env vars, and features still exist in the code? Mark \`outdated\` only with evidence.
|
|
59967
|
+
- **architecture.md** — does it exist? Is the repo structured enough to warrant one? Look at the
|
|
59968
|
+
top-level layout, number of modules/services, and whether there's a clear separation worth
|
|
59969
|
+
documenting.
|
|
59970
|
+
- **deps.md** — does it exist? If yes, does it match the actual manifests/lockfiles? If missing,
|
|
59971
|
+
are there real dependencies worth documenting?
|
|
59972
|
+
|
|
59973
|
+
3. **Consult Dosu MCP** (see above) to enrich and cross-check.
|
|
59974
|
+
|
|
59975
|
+
4. **Write \`.dosu/audit.json\`** following [audit-findings-schema.md](audit-findings-schema.md).
|
|
59976
|
+
Create the \`.dosu/\` directory if needed. Write one \`items\` entry per type you assessed.
|
|
59977
|
+
|
|
59978
|
+
5. **Tell the user to run the CLI.** End with a short message, e.g.:
|
|
59979
|
+
|
|
59980
|
+
> Audit complete — I wrote \`.dosu/audit.json\`. Run \`dosu audit\` to choose which docs Dosu
|
|
59981
|
+
> should generate; it will open a PR with the ones you pick.
|
|
59982
|
+
|
|
59983
|
+
Do not attempt to generate or commit the docs yourself.
|
|
59984
|
+
|
|
59985
|
+
## Example \`.dosu/audit.json\`
|
|
59986
|
+
|
|
59987
|
+
\`\`\`json
|
|
59988
|
+
{
|
|
59989
|
+
"version": 1,
|
|
59990
|
+
"generated_at": "2026-06-24T12:00:00Z",
|
|
59991
|
+
"repo": { "remote": "git@github.com:acme/widget.git", "slug": "acme/widget" },
|
|
59992
|
+
"items": [
|
|
59993
|
+
{
|
|
59994
|
+
"task": "generate-agents-md", "type": "agents", "file": "AGENTS.md",
|
|
59995
|
+
"status": "missing", "action": "create", "can_help": true, "confidence": "high",
|
|
59996
|
+
"rationale": "No AGENTS.md; repo has documented \`pnpm test\`/\`pnpm build\` scripts and a clear packages/ layout worth capturing for agents.",
|
|
59997
|
+
"evidence": ["package.json", "packages/", "CONTRIBUTING.md"]
|
|
59998
|
+
},
|
|
59999
|
+
{
|
|
60000
|
+
"task": "refresh-readme", "type": "readme", "file": "README.md",
|
|
60001
|
+
"status": "outdated", "action": "update", "can_help": true, "confidence": "medium",
|
|
60002
|
+
"rationale": "README's Getting Started references a \`make bootstrap\` target that no longer exists; setup now uses \`pnpm install\`.",
|
|
60003
|
+
"evidence": ["README.md:24", "Makefile", "package.json"]
|
|
60004
|
+
},
|
|
60005
|
+
{
|
|
60006
|
+
"task": "generate-architecture-md", "type": "architecture", "file": "architecture.md",
|
|
60007
|
+
"status": "missing", "action": "skip", "can_help": false, "confidence": "high",
|
|
60008
|
+
"rationale": "Single-package repo with one entry point; not enough structure to justify a separate architecture doc yet.",
|
|
60009
|
+
"evidence": ["src/index.ts"]
|
|
60010
|
+
},
|
|
60011
|
+
{
|
|
60012
|
+
"task": "generate-deps-md", "type": "deps", "file": "deps.md",
|
|
60013
|
+
"status": "missing", "action": "create", "can_help": true, "confidence": "medium",
|
|
60014
|
+
"rationale": "No deps doc; package.json has ~30 runtime deps across HTTP, DB, and queue concerns worth summarizing.",
|
|
60015
|
+
"evidence": ["package.json", "pnpm-lock.yaml"]
|
|
60016
|
+
}
|
|
60017
|
+
]
|
|
60018
|
+
}
|
|
60019
|
+
\`\`\`
|
|
60020
|
+
`,
|
|
60021
|
+
executable: false
|
|
60022
|
+
},
|
|
60023
|
+
{
|
|
60024
|
+
path: "references/commands.md",
|
|
60025
|
+
content: `# Dosu CLI command reference
|
|
60026
|
+
|
|
60027
|
+
This file is the detailed source for the current command surface. Optional flags are in brackets. Only commands showing \`--json\` support structured JSON. Run the nested \`--help\` if the installed CLI differs.
|
|
60028
|
+
|
|
60029
|
+
## Authentication and setup
|
|
60030
|
+
|
|
60031
|
+
\`\`\`text
|
|
60032
|
+
dosu login [--request | --check <ticket>] [--json] [--no-browser]
|
|
60033
|
+
dosu logout
|
|
60034
|
+
dosu status [--json]
|
|
60035
|
+
dosu setup [--deployment <id>] [--mode <oss|cloud>] [--agent --tool <id>]
|
|
60036
|
+
[--login-ticket <ticket>]
|
|
60037
|
+
\`\`\`
|
|
60038
|
+
|
|
60039
|
+
- \`--request\` and \`--check\` are mutually exclusive login modes.
|
|
60040
|
+
- \`setup --agent\` requires \`--tool\`, emits NDJSON, and exits instead of waiting for a browser callback.
|
|
60041
|
+
|
|
60042
|
+
## Libraries
|
|
60043
|
+
|
|
60044
|
+
\`\`\`text
|
|
60045
|
+
dosu libraries list [--json]
|
|
60046
|
+
dosu libraries info <library-id> [--json]
|
|
60047
|
+
dosu libraries create --name <name> [--visibility public|internal|private] [--json]
|
|
60048
|
+
dosu libraries update <library-id> [--name <name>]
|
|
60049
|
+
[--visibility public|internal|private] [--confirm] [--json]
|
|
60050
|
+
dosu libraries delete <library-id> [--confirm] [--json]
|
|
60051
|
+
\`\`\`
|
|
60052
|
+
|
|
60053
|
+
- Library and source IDs in this section must be UUID v4. Names are nonempty and at most 50 characters. Omitted visibility uses the App default, \`internal\`. \`update\` requires at least one changed field.
|
|
60054
|
+
- \`update\` and \`delete\` prompt only in an interactive non-JSON terminal; agents pass \`--confirm\` after authorization.
|
|
60055
|
+
- The last Library in an organization cannot be deleted. A successful delete hides it immediately; child-data cleanup continues asynchronously.
|
|
60056
|
+
|
|
60057
|
+
### Library documentation config
|
|
60058
|
+
|
|
60059
|
+
\`\`\`text
|
|
60060
|
+
dosu libraries config get <library-id> [--json]
|
|
60061
|
+
dosu libraries config set <library-id> <setting> --value <json> [--confirm] [--json]
|
|
60062
|
+
\`\`\`
|
|
60063
|
+
|
|
60064
|
+
Settings and values:
|
|
60065
|
+
|
|
60066
|
+
| Setting | JSON value |
|
|
60067
|
+
|---|---|
|
|
60068
|
+
| \`commit_to_trigger_pr\` | boolean |
|
|
60069
|
+
| \`default_accept_review\` | boolean |
|
|
60070
|
+
| \`default_save_publish\` | boolean |
|
|
60071
|
+
| \`review_timeout_days\` | \`7\`, \`14\`, \`30\`, or \`90\` |
|
|
60072
|
+
|
|
60073
|
+
\`set\` reads the current version immediately before writing and sends that version with the mutation.
|
|
60074
|
+
|
|
60075
|
+
### Library sources
|
|
60076
|
+
|
|
60077
|
+
\`\`\`text
|
|
60078
|
+
dosu libraries sources list <library-id> [--json]
|
|
60079
|
+
dosu libraries sources attach <library-id> <source-id...> [--confirm] [--json]
|
|
60080
|
+
dosu libraries sources detach <library-id> <source-id...> [--confirm] [--json]
|
|
60081
|
+
|
|
60082
|
+
dosu libraries sources config get <library-id> <source-id> [--json]
|
|
60083
|
+
dosu libraries sources config update <library-id> <source-id>
|
|
60084
|
+
[--issues on|off] [--pull-requests on|off] [--discussions on|off] [--wiki on|off]
|
|
60085
|
+
[--include-patterns <json-string-array>] [--exclude-patterns <json-string-array>]
|
|
60086
|
+
[--confirm] [--json]
|
|
60087
|
+
\`\`\`
|
|
60088
|
+
|
|
60089
|
+
- \`attach\` and \`detach\` require one or more UUID source IDs. Repeated IDs are deduplicated.
|
|
60090
|
+
- Detaching archives pages that source synced into this Library; copies in other Libraries are unaffected.
|
|
60091
|
+
- Source config requires at least one option. GitHub accepts every option above; GitLab accepts only include/exclude patterns. The App resolves the provider.
|
|
60092
|
+
- Pattern options replace the list. Use \`[]\` to clear it.
|
|
60093
|
+
|
|
60094
|
+
### Library Monitor
|
|
60095
|
+
|
|
60096
|
+
\`\`\`text
|
|
60097
|
+
dosu libraries monitors list <library-id> [--json]
|
|
60098
|
+
dosu libraries monitors update <library-id> <source-id>
|
|
60099
|
+
[--enabled on|off] [--paths <json-string-array>]
|
|
60100
|
+
[--up-to-date-behavior emoji|comment|silent] [--confirm] [--json]
|
|
60101
|
+
\`\`\`
|
|
60102
|
+
|
|
60103
|
+
\`update\` requires at least one option. Monitor supports GitHub, GitLab, and Azure DevOps. It performs first-time setup for an attached supported source, reusing existing deployment infrastructure when available. When no Monitor row exists, omitted \`--enabled\`, paths, and behavior default to \`true\`, \`[]\`, and \`emoji\`.
|
|
60104
|
+
|
|
60105
|
+
## Agents
|
|
60106
|
+
|
|
60107
|
+
\`\`\`text
|
|
60108
|
+
dosu agents list [--json]
|
|
60109
|
+
dosu agents info <agent-id> [--json]
|
|
60110
|
+
dosu agents create --library <library-id> --source <source-id>
|
|
60111
|
+
[--name <name>] [--guidelines <text>] [--json]
|
|
60112
|
+
dosu agents update <agent-id> [--name <name>] [--enabled on|off]
|
|
60113
|
+
[--guidelines <text> | --clear-guidelines] [--confirm] [--json]
|
|
60114
|
+
dosu agents delete <agent-id> [--confirm] [--json]
|
|
60115
|
+
dosu agents move <agent-id> --library <library-id> [--confirm] [--json]
|
|
60116
|
+
|
|
60117
|
+
dosu agents config get <agent-id> [--json]
|
|
60118
|
+
dosu agents config set <agent-id> <existing.leaf.path>
|
|
60119
|
+
--value <json> [--confirm] [--json]
|
|
60120
|
+
\`\`\`
|
|
60121
|
+
|
|
60122
|
+
- Agent, Library, and source IDs in this section must be UUID v4. \`create\` accepts an existing GitHub, GitLab, Slack, or Teams source. The App supplies provider defaults, enables the Agent, and starts Mention-only reply behavior. Omitted name uses the source name.
|
|
60123
|
+
- Agent names are at most 80 characters; guidelines are at most 20,000 characters.
|
|
60124
|
+
- \`update\` requires at least one option. \`--guidelines\` conflicts with \`--clear-guidelines\`.
|
|
60125
|
+
- Config \`set\` changes one existing non-object leaf. Read the config first to select a valid path and value type.
|
|
60126
|
+
- \`move\` replaces the Agent's Library and returns the updated Agent. It does not report any historical-data migration.
|
|
60127
|
+
|
|
60128
|
+
## Knowledge and documents
|
|
60129
|
+
|
|
60130
|
+
\`\`\`text
|
|
60131
|
+
dosu ask <question> [--session <id>] [--timeout <seconds>] [--json]
|
|
60132
|
+
dosu knowledge search <query> [--limit <positive-int>] [--json] # default 10
|
|
60133
|
+
dosu knowledge list [--json]
|
|
60134
|
+
|
|
60135
|
+
dosu docs list [--search <query>] [--topic <id>] [--limit <positive-int>] [--json]
|
|
60136
|
+
dosu docs get <id> [--revision <positive-int>] [--json]
|
|
60137
|
+
dosu docs create --title <title> [--body <markdown> | --body-file <path>] [--json]
|
|
60138
|
+
dosu docs update <id> [--title <title>] [--body <markdown> | --body-file <path>] [--json]
|
|
60139
|
+
dosu docs archive <id> [--json]
|
|
60140
|
+
dosu docs unarchive <id> [--json]
|
|
60141
|
+
dosu docs delete <id> [--json]
|
|
60142
|
+
dosu docs versions <id> [--json]
|
|
60143
|
+
dosu docs restore <id> --revision <positive-int> [--json]
|
|
60144
|
+
dosu docs generate --title <title> [--instructions <text>] [--json]
|
|
60145
|
+
dosu docs auto-tag <id> [--json]
|
|
60146
|
+
dosu docs import <platform> --files <comma-separated-ids> [--json]
|
|
60147
|
+
dosu docs import-status <task-id> [--json]
|
|
60148
|
+
dosu docs publish <id> --to <platform> [target flags] [--json]
|
|
60149
|
+
dosu docs sync-back <id> [--json]
|
|
60150
|
+
\`\`\`
|
|
60151
|
+
|
|
60152
|
+
- Document list defaults to 20. \`create\` and \`update\` reject combining \`--body\` with \`--body-file\`; \`update\` requires at least one field.
|
|
60153
|
+
- Import platforms: \`github\`, \`gitlab\`, \`azure_devops\`, \`confluence\`, \`notion\`, \`coda\`.
|
|
60154
|
+
- Publish platforms: the same six. Target flags are \`--repo-id\`, \`--project-id\`, \`--parent-page-id\`, \`--doc-id\`, \`--directory\`, and \`--data-source-id\`; Azure DevOps requires \`--data-source-id\`. Other target validation may occur in the backend.
|
|
60155
|
+
- \`generate\`, \`auto-tag\`, import, publish, and sync operations may be asynchronous. Use the returned task/status identifiers rather than assuming completion.
|
|
60156
|
+
|
|
60157
|
+
## Review
|
|
60158
|
+
|
|
60159
|
+
Read [review-workflow.md](review-workflow.md) before mutating a review item.
|
|
60160
|
+
|
|
60161
|
+
\`\`\`text
|
|
60162
|
+
dosu review list [--json]
|
|
60163
|
+
dosu review diff <id> [--json]
|
|
60164
|
+
dosu review edit <id> [--title <title>] [--body <markdown> | --body-file <path>] [--json]
|
|
60165
|
+
dosu review context <thread-id> [--json]
|
|
60166
|
+
dosu review approve <id> [--confirm] [--json]
|
|
60167
|
+
dosu review reject <id> [--confirm] [--json]
|
|
60168
|
+
dosu review revert <id> [--json]
|
|
60169
|
+
\`\`\`
|
|
60170
|
+
|
|
60171
|
+
\`edit\` requires at least one field. \`approve\` and \`reject\` do not write without interactive confirmation or \`--confirm\`.
|
|
60172
|
+
|
|
60173
|
+
## Sources, integrations, members, and organization
|
|
60174
|
+
|
|
60175
|
+
\`\`\`text
|
|
60176
|
+
dosu sources list [--json]
|
|
60177
|
+
dosu sources info <id> [--json]
|
|
60178
|
+
dosu sources sync <id> [--json]
|
|
60179
|
+
dosu sources update <id> [--name <name>] [--description <text>] [--json]
|
|
60180
|
+
dosu sources delete <id> [--json]
|
|
60181
|
+
dosu sources connect [github] [--json] [--timeout <seconds>] [--no-open]
|
|
60182
|
+
dosu sources create github --repo <owner/name> [--library <id>] [--confirm] [--json]
|
|
60183
|
+
|
|
60184
|
+
dosu integrations list [--json]
|
|
60185
|
+
dosu integrations status <platform> [--json]
|
|
60186
|
+
dosu integrations slack-channels [--json]
|
|
60187
|
+
dosu integrations slack-join <channel-id> [--json]
|
|
60188
|
+
dosu integrations github-collaborators <positive-repository-id> [--json]
|
|
60189
|
+
|
|
60190
|
+
dosu members invite <email> [--role admin|member] [--json] # default member
|
|
60191
|
+
dosu org info [--json]
|
|
60192
|
+
\`\`\`
|
|
60193
|
+
|
|
60194
|
+
- \`sources update\` requires \`--name\` or \`--description\`.
|
|
60195
|
+
- \`sources connect\` currently supports only \`github\`: it prints an install URL for the user to
|
|
60196
|
+
open, then waits for the GitHub App install to complete (default 600s). With \`--json\` it emits
|
|
60197
|
+
NDJSON events — \`awaiting_install\` (give the \`url\` to the user), then \`installed\` with
|
|
60198
|
+
\`new_repositories\`, or \`timeout\` (exit 1). Other providers exit 1 with a web-app handoff URL.
|
|
60199
|
+
- \`sources create\` wires an installed GitHub repo into a Library: it creates (or reuses) the
|
|
60200
|
+
repo's data source + deployment, attaches it, and verifies the first sync. \`--library\` defaults
|
|
60201
|
+
to the active Library. A repo not listed means the GitHub App lacks access — run
|
|
60202
|
+
\`sources connect github\` first. Forks can't be connected.
|
|
60203
|
+
- Integration status choices: \`github\`, \`gitlab\`, \`azure_devops\`, \`slack\`, \`confluence\`, \`notion\`, \`coda\`, \`teams\`. GitHub, Slack, and Teams currently return \`connected: null\` because CLI status probing is unavailable for them.
|
|
60204
|
+
- The CLI has no member list/remove/request commands; \`members invite\` is its only member operation.
|
|
60205
|
+
|
|
60206
|
+
## Threads, Topics, suggestions, and analytics
|
|
60207
|
+
|
|
60208
|
+
\`\`\`text
|
|
60209
|
+
dosu threads list [--status pending|resolved|archived] [--search <query>]
|
|
60210
|
+
[--limit <1..100>] [--json] # default 20
|
|
60211
|
+
dosu threads get <id> [--limit <-1|positive-int>] [--json] # default 20
|
|
60212
|
+
dosu threads archive <id> [--json]
|
|
60213
|
+
|
|
60214
|
+
dosu topics list [--json]
|
|
60215
|
+
dosu topics pages <topic-id> [--search <query>] [--limit <positive-int>] [--json]
|
|
60216
|
+
|
|
60217
|
+
dosu suggest list [--json]
|
|
60218
|
+
dosu suggest generate [--json]
|
|
60219
|
+
dosu suggest reject <id> [--json]
|
|
60220
|
+
|
|
60221
|
+
dosu analytics [--days <positive-int>] [--json] # default 30
|
|
60222
|
+
\`\`\`
|
|
60223
|
+
|
|
60224
|
+
Topics are read-only. The CLI has no \`tags\` command and no suggestion-accept command.
|
|
60225
|
+
|
|
60226
|
+
## MCP deployments and local utilities
|
|
60227
|
+
|
|
60228
|
+
\`\`\`text
|
|
60229
|
+
dosu deployments list [--json]
|
|
60230
|
+
dosu deployments info [--json]
|
|
60231
|
+
dosu deployments switch <id> [--json]
|
|
60232
|
+
|
|
60233
|
+
dosu mcp list
|
|
60234
|
+
dosu mcp add <agent> [--global] [--show-secret]
|
|
60235
|
+
dosu skill install | remove | update
|
|
60236
|
+
dosu telemetry status [--json]
|
|
60237
|
+
dosu telemetry enable | disable | reset
|
|
60238
|
+
dosu insights
|
|
60239
|
+
dosu upgrade
|
|
60240
|
+
dosu logs [--tail [n]] [--clear]
|
|
60241
|
+
\`\`\`
|
|
60242
|
+
|
|
60243
|
+
\`deployments\` selects the MCP deployment stored in local config; it is distinct from \`agents\`. \`insights\` opens an interactive visual report. \`logs --clear\` deletes the CLI log file.
|
|
60244
|
+
|
|
60245
|
+
## Codebase audit
|
|
60246
|
+
|
|
60247
|
+
\`\`\`text
|
|
60248
|
+
dosu audit [--findings <path>] [--data-source-id <id>]
|
|
60249
|
+
[--tasks <comma-separated-task-ids> | --yes] [--list-tasks] [--json]
|
|
60250
|
+
\`\`\`
|
|
60251
|
+
|
|
60252
|
+
The coding agent writes the findings; Dosu generates the selected docs. Follow [audit.md](audit.md) and [audit-findings-schema.md](audit-findings-schema.md).
|
|
60253
|
+
`,
|
|
60254
|
+
executable: false
|
|
60255
|
+
},
|
|
60256
|
+
{
|
|
60257
|
+
path: "references/review-workflow.md",
|
|
60258
|
+
content: `# Review workflow
|
|
60259
|
+
|
|
60260
|
+
How to work Dosu's review queue from the CLI: triage pending items, read the
|
|
60261
|
+
diff, optionally edit, and apply a decision — safely.
|
|
60262
|
+
|
|
60263
|
+
The queue holds **document versions** (AI-generated, user-edited, synced from
|
|
60264
|
+
source, or API-created) and **draft messages**, all surfaced through the same
|
|
60265
|
+
\`dosu review\` commands. Items are keyed on a single \`page-version-id\` so
|
|
60266
|
+
\`list\` → \`diff\` → \`edit\` → \`approve\`/\`reject\` all share one ID.
|
|
60267
|
+
|
|
60268
|
+
> \`list\` returns only the most recent pending items (server-capped, currently
|
|
60269
|
+
> 50) and does not flag truncation. If the queue is large, don't assume \`list\`
|
|
60270
|
+
> shows everything.
|
|
60271
|
+
|
|
60272
|
+
## Scope tool access for a review session
|
|
60273
|
+
|
|
60274
|
+
Approving and rejecting are destructive and outward-facing. When you spin up an
|
|
60275
|
+
agent session dedicated to reviewing, scope it to just the review commands:
|
|
60276
|
+
|
|
60277
|
+
\`\`\`yaml
|
|
60278
|
+
allowed-tools: Bash(dosu review:*)
|
|
60279
|
+
\`\`\`
|
|
60280
|
+
|
|
60281
|
+
This lets the agent triage, diff, and edit, but keeps it from running unrelated
|
|
60282
|
+
CLI commands during a review pass.
|
|
60283
|
+
|
|
60284
|
+
## The flow
|
|
60285
|
+
|
|
60286
|
+
\`\`\`bash
|
|
60287
|
+
# 1. Triage — what's pending? Columns: ID, Kind, Title, Source, Status, Created.
|
|
60288
|
+
dosu review list --json
|
|
60289
|
+
|
|
60290
|
+
# 2. Inspect — read the exact change before deciding anything.
|
|
60291
|
+
dosu review diff <page-version-id> --json
|
|
60292
|
+
|
|
60293
|
+
# 3. (optional) Edit in place instead of rejecting a near-miss.
|
|
60294
|
+
dosu review edit <page-version-id> --body-file ./revised.md # or --body / --title
|
|
60295
|
+
|
|
60296
|
+
# 4. Decide — only on the item the user named, only after they OK it.
|
|
60297
|
+
dosu review approve <page-version-id> --confirm --json
|
|
60298
|
+
dosu review reject <page-version-id> --confirm --json
|
|
60299
|
+
|
|
60300
|
+
# Undo a decision — back to pending.
|
|
60301
|
+
dosu review revert <page-version-id> --json
|
|
60302
|
+
\`\`\`
|
|
60303
|
+
|
|
60304
|
+
### \`--confirm\` is mandatory for agents
|
|
60305
|
+
|
|
60306
|
+
\`approve\` and \`reject\` only prompt interactively in a TTY *without* \`--json\`.
|
|
60307
|
+
The skill always passes \`--json\`, which suppresses both the diff preview and
|
|
60308
|
+
the prompt — so without \`--confirm\` the command changes nothing and returns
|
|
60309
|
+
\`{ "applied": false, "confirmRequired": true }\`. Run \`dosu review diff <id>\` to
|
|
60310
|
+
see the change, then pass \`--confirm\` to apply — only after the user has
|
|
60311
|
+
approved that specific item.
|
|
60312
|
+
|
|
60313
|
+
## Reading the \`Source\` column
|
|
60314
|
+
|
|
60315
|
+
\`Source\` is the humanized \`origin\` field:
|
|
60316
|
+
|
|
60317
|
+
| \`origin\` | Source | Meaning |
|
|
60318
|
+
|---|---|---|
|
|
60319
|
+
| \`manual_update\` | User created / User updated | A teammate authored or edited the doc |
|
|
60320
|
+
| \`llm_generated\` | AI generated | Dosu drafted the change |
|
|
60321
|
+
| \`sync_upstream\` | Synced from source | Came in from a connected source (Notion/Confluence/GitHub) |
|
|
60322
|
+
| \`api_update\` | Created via API | Pushed in programmatically |
|
|
60323
|
+
|
|
60324
|
+
## Feeding PR / thread context
|
|
60325
|
+
|
|
60326
|
+
A review often originates from a conversation thread (a GitHub issue, a Slack
|
|
60327
|
+
message, a sync-back PR). Pull that context before deciding:
|
|
60328
|
+
|
|
60329
|
+
\`\`\`bash
|
|
60330
|
+
dosu review context <thread-id> --json
|
|
60331
|
+
\`\`\`
|
|
60332
|
+
|
|
60333
|
+
It returns the review \`type\`, the review/published page IDs, and — when the
|
|
60334
|
+
change round-trips to an external system — a **Sync PR URL**. Use it to:
|
|
60335
|
+
|
|
60336
|
+
- show the user where the change came from and where approval will land, and
|
|
60337
|
+
- read the originating discussion so the decision matches intent.
|
|
60338
|
+
|
|
60339
|
+
## Safety rules
|
|
60340
|
+
|
|
60341
|
+
- **Explicit item only.** Decide on the \`id\` the user named. "Review my queue"
|
|
60342
|
+
→ run \`list\` and show it; never decide on their behalf.
|
|
60343
|
+
- **Diff before deciding.** Always \`diff\` and surface the change first.
|
|
60344
|
+
- **Never batch-accept.** No loop over \`list\` that approves everything. One
|
|
60345
|
+
item, one confirmation.
|
|
60346
|
+
- **Extra care for sync/PR origins.** \`Synced from source\` items and anything
|
|
60347
|
+
with a Sync PR URL push back to an upstream system on approval. Call it out
|
|
60348
|
+
and get explicit sign-off.
|
|
60349
|
+
`,
|
|
60350
|
+
executable: false
|
|
60351
|
+
},
|
|
60352
|
+
{
|
|
60353
|
+
path: "references/workflows.md",
|
|
60354
|
+
content: `# Dosu CLI workflows
|
|
60355
|
+
|
|
60356
|
+
Use these patterns to compose commands. Replace placeholders with IDs read from JSON output; never guess them. See [commands.md](commands.md) for exact flags and choices.
|
|
60357
|
+
|
|
60358
|
+
## Configure Dosu for a coding agent
|
|
60359
|
+
|
|
60360
|
+
\`\`\`bash
|
|
60361
|
+
dosu setup --agent --tool <tool-id>
|
|
60362
|
+
\`\`\`
|
|
60363
|
+
|
|
60364
|
+
Read every NDJSON event:
|
|
60365
|
+
|
|
60366
|
+
1. On \`need_user_action\`, give the returned URL to the user and stop.
|
|
60367
|
+
2. After the user confirms sign-in, run the returned \`resume_command\` verbatim.
|
|
60368
|
+
3. On \`pending\`, wait for the user and repeat that command.
|
|
60369
|
+
4. On \`multiple_deployments\`, list MCP deployments, let the user choose, and retry with \`--deployment <id>\`.
|
|
60370
|
+
5. Treat \`done\` as setup completion, then verify with \`dosu status --json\`.
|
|
60371
|
+
|
|
60372
|
+
## Onboard from scratch (guided)
|
|
60373
|
+
|
|
60374
|
+
Use this flow when the user asks to "set up Dosu", "create a library and set it up", or any
|
|
60375
|
+
end-to-end onboarding. It is a conversation, not a script: never invent names, never auto-pick
|
|
60376
|
+
sources, and stop at every checkpoint below until the user answers. Run each mutation only after
|
|
60377
|
+
its checkpoint. One step per turn is better than one turn with every step.
|
|
60378
|
+
|
|
60379
|
+
**Step 0 — Discover (read-only, no confirmation needed).**
|
|
60380
|
+
|
|
60381
|
+
\`\`\`bash
|
|
60382
|
+
dosu status --json
|
|
60383
|
+
dosu sources list --json
|
|
60384
|
+
dosu libraries list --json
|
|
60385
|
+
\`\`\`
|
|
60386
|
+
|
|
60387
|
+
If not configured, run the "Configure Dosu for a coding agent" flow first.
|
|
60388
|
+
|
|
60389
|
+
**Checkpoint 1 — Scope.** Present a short summary of the connected sources (name + provider, not
|
|
60390
|
+
raw JSON) and any existing Libraries, then ask and wait:
|
|
60391
|
+
|
|
60392
|
+
1. Which source(s) should the new Library use? Existing ones, a new one, or both.
|
|
60393
|
+
2. What should the Library be called? Suggest a name derived from the chosen sources, but let the
|
|
60394
|
+
user decide.
|
|
60395
|
+
3. Visibility: default \`internal\`; mention \`private\`/\`public\` only if relevant (warn about the
|
|
60396
|
+
public-Library boundary from [SKILL.md](../SKILL.md)).
|
|
60397
|
+
4. For each chosen GitHub repository: Monitor will be enabled with defaults (whole repository,
|
|
60398
|
+
\`emoji\`) unless they opt out.
|
|
60399
|
+
|
|
60400
|
+
**Step 0.5 — Connect a new source (only when the user asked for one).** Ask which provider. For
|
|
60401
|
+
GitHub, run the CLI bridge — do not send the user hunting through the App:
|
|
60402
|
+
|
|
60403
|
+
\`\`\`bash
|
|
60404
|
+
dosu sources connect github --json
|
|
60405
|
+
\`\`\`
|
|
60406
|
+
|
|
60407
|
+
Give the user the \`url\` from the \`awaiting_install\` event and wait; the command completes on its
|
|
60408
|
+
own when the install finishes and reports \`new_repositories\`. For any other provider (Slack, web
|
|
60409
|
+
docs, Notion, Coda, Confluence, ...) the connect flow is web-only: give the user the App URL the
|
|
60410
|
+
command prints, wait for them to confirm, then re-run \`dosu sources list --json\` to pick up the
|
|
60411
|
+
new source.
|
|
60412
|
+
|
|
60413
|
+
**Step 1 — Create and attach (after the user answers).**
|
|
60414
|
+
|
|
60415
|
+
\`\`\`bash
|
|
60416
|
+
dosu libraries create --name "<user-approved name>" --json
|
|
60417
|
+
dosu libraries sources attach <library-id> <existing-source-ids...> --confirm --json
|
|
60418
|
+
dosu sources create github --repo <owner/name> --library <library-id> --confirm --json
|
|
60419
|
+
dosu libraries monitors update <library-id> <repository-source-id> --enabled on --confirm --json
|
|
60420
|
+
\`\`\`
|
|
60421
|
+
|
|
60422
|
+
Use \`libraries sources attach\` for sources that already exist; use \`sources create\` for a GitHub
|
|
60423
|
+
repo that became visible via \`sources connect\` but has no data source yet (it creates, attaches,
|
|
60424
|
+
and verifies the first sync in one receipt).
|
|
60425
|
+
|
|
60426
|
+
Report each receipt in one line as it lands (Library ID, sources attached, Monitor state).
|
|
60427
|
+
|
|
60428
|
+
**Checkpoint 2 — Agent (optional).** Ask whether the user wants an Agent (GitHub/GitLab/Slack/Teams
|
|
60429
|
+
responder) on one of the attached sources. Only on yes:
|
|
60430
|
+
|
|
60431
|
+
\`\`\`bash
|
|
60432
|
+
dosu agents create --library <library-id> --source <source-id> --name "<user-approved name>" --json
|
|
60433
|
+
\`\`\`
|
|
60434
|
+
|
|
60435
|
+
A \`CONFLICT\` (409) means that data source already has an Agent — one Agent per source. Report which
|
|
60436
|
+
source conflicted and offer the alternatives: pick a different source, or (only with explicit
|
|
60437
|
+
authorization) \`dosu agents move\` the existing Agent, which removes it from its current Library.
|
|
60438
|
+
|
|
60439
|
+
**Step 2 — Verify and hand off.**
|
|
60440
|
+
|
|
60441
|
+
\`\`\`bash
|
|
60442
|
+
dosu libraries info <library-id> --json
|
|
60443
|
+
dosu libraries sources list <library-id> --json
|
|
60444
|
+
dosu libraries monitors list <library-id> --json
|
|
60445
|
+
\`\`\`
|
|
60446
|
+
|
|
60447
|
+
Summarize the final state. Creating an MCP deployment for the new Library is not available in the
|
|
60448
|
+
CLI; if the user wants their MCP/CLI target pointed at this Library, send them to the App to create
|
|
60449
|
+
the MCP deployment, then run \`dosu deployments switch\`.
|
|
60450
|
+
|
|
60451
|
+
## Create a Library from existing sources
|
|
60452
|
+
|
|
60453
|
+
This works with any number or mix of organization sources.
|
|
60454
|
+
|
|
60455
|
+
\`\`\`bash
|
|
60456
|
+
# Discover connected sources and select exact IDs by provider/name.
|
|
60457
|
+
dosu sources list --json
|
|
60458
|
+
|
|
60459
|
+
# Create the Library; capture its id. Omitted visibility defaults to \`internal\`;
|
|
60460
|
+
# pass --visibility public|internal|private only when the user asks for it.
|
|
60461
|
+
dosu libraries create --name "Incident Response" --json
|
|
60462
|
+
|
|
60463
|
+
# The user's explicit request authorizes these exact attachments.
|
|
60464
|
+
dosu libraries sources attach <library-id> <repository-source-id> <handbook-source-id> \\
|
|
60465
|
+
--confirm --json
|
|
60466
|
+
|
|
60467
|
+
# Enable the default for each newly attached GitHub repository unless the user opted out.
|
|
60468
|
+
dosu libraries monitors update <library-id> <repository-source-id> \\
|
|
60469
|
+
--enabled on --confirm --json
|
|
60470
|
+
|
|
60471
|
+
# Verify the final state, not just mutation receipts.
|
|
60472
|
+
dosu libraries info <library-id> --json
|
|
60473
|
+
dosu libraries sources list <library-id> --json
|
|
60474
|
+
dosu libraries monitors list <library-id> --json
|
|
60475
|
+
\`\`\`
|
|
60476
|
+
|
|
60477
|
+
Apply the connection and public-Library safety boundaries from [SKILL.md](../SKILL.md) before attaching.
|
|
60478
|
+
|
|
60479
|
+
## Change an existing Library safely
|
|
60480
|
+
|
|
60481
|
+
\`\`\`bash
|
|
60482
|
+
dosu libraries list --json
|
|
60483
|
+
dosu libraries info <library-id> --json
|
|
60484
|
+
|
|
60485
|
+
# Rename or change visibility only after the exact target/change is authorized.
|
|
60486
|
+
dosu libraries update <library-id> --name "Operations Handbook" --confirm --json
|
|
60487
|
+
|
|
60488
|
+
# Read before changing one documentation setting.
|
|
60489
|
+
dosu libraries config get <library-id> --json
|
|
60490
|
+
dosu libraries config set <library-id> review_timeout_days --value 30 --confirm --json
|
|
60491
|
+
\`\`\`
|
|
60492
|
+
|
|
60493
|
+
## Create and configure an Agent
|
|
60494
|
+
|
|
60495
|
+
\`\`\`bash
|
|
60496
|
+
# Select a Library and an existing GitHub, GitLab, Slack, or Teams source.
|
|
60497
|
+
dosu libraries list --json
|
|
60498
|
+
dosu sources list --json
|
|
60499
|
+
|
|
60500
|
+
dosu agents create --library <library-id> --source <source-id> \\
|
|
60501
|
+
--name "Repository Helper" --json
|
|
60502
|
+
|
|
60503
|
+
dosu agents info <agent-id> --json
|
|
60504
|
+
dosu agents config get <agent-id> --json
|
|
60505
|
+
|
|
60506
|
+
# Change one leaf only after reading the current structure.
|
|
60507
|
+
dosu agents config set <agent-id> issues.auto_reply.review_required \\
|
|
60508
|
+
--value true --confirm --json
|
|
60509
|
+
\`\`\`
|
|
60510
|
+
|
|
60511
|
+
To move the Agent, confirm the destination and verify the returned \`space_id\`:
|
|
60512
|
+
|
|
60513
|
+
\`\`\`bash
|
|
60514
|
+
dosu agents move <agent-id> --library <destination-library-id> --confirm --json
|
|
60515
|
+
\`\`\`
|
|
60516
|
+
|
|
60517
|
+
## Configure a Library source and Monitor
|
|
60518
|
+
|
|
60519
|
+
\`\`\`bash
|
|
60520
|
+
dosu libraries sources config get <library-id> <source-id> --json
|
|
60521
|
+
dosu libraries sources config update <library-id> <source-id> \\
|
|
60522
|
+
--include-patterns '["docs/**","*.md"]' \\
|
|
60523
|
+
--exclude-patterns '["archive/**"]' --confirm --json
|
|
60524
|
+
|
|
60525
|
+
dosu libraries monitors list <library-id> --json
|
|
60526
|
+
dosu libraries monitors update <library-id> <source-id> \\
|
|
60527
|
+
--enabled on --paths '["docs/**"]' \\
|
|
60528
|
+
--up-to-date-behavior silent --confirm --json
|
|
60529
|
+
\`\`\`
|
|
60530
|
+
|
|
60531
|
+
## Find information and inspect its source
|
|
60532
|
+
|
|
60533
|
+
\`\`\`bash
|
|
60534
|
+
dosu ask "How is access control enforced?" --json
|
|
60535
|
+
dosu knowledge search "access control" --json
|
|
60536
|
+
dosu docs get <page-id> --json
|
|
60537
|
+
\`\`\`
|
|
60538
|
+
|
|
60539
|
+
Use \`ask\` for a synthesized answer. Use \`knowledge search\` and \`docs get\` when the user wants the underlying documents.
|
|
60540
|
+
|
|
60541
|
+
## Import external documents
|
|
60542
|
+
|
|
60543
|
+
\`\`\`bash
|
|
60544
|
+
dosu sources list --json
|
|
60545
|
+
dosu docs import <platform> --files <comma-separated-ids> --json
|
|
60546
|
+
dosu docs import-status <task-id> --json
|
|
60547
|
+
\`\`\`
|
|
60548
|
+
|
|
60549
|
+
Capture the returned task ID. Poll only when the user asked you to wait for completion.
|
|
60550
|
+
|
|
60551
|
+
## Review one pending item
|
|
60552
|
+
|
|
60553
|
+
\`\`\`bash
|
|
60554
|
+
dosu review list --json
|
|
60555
|
+
dosu review diff <item-id> --json
|
|
60556
|
+
dosu review approve <item-id> --confirm --json
|
|
60557
|
+
\`\`\`
|
|
60558
|
+
|
|
60559
|
+
Use \`reject\` instead of \`approve\` only for the same explicitly authorized item. Follow [review-workflow.md](review-workflow.md) for edits, draft replies, upstream sync, and rollback.
|
|
60560
|
+
|
|
60561
|
+
## Audit repository documentation
|
|
60562
|
+
|
|
60563
|
+
Follow [audit.md](audit.md) to inspect the repository and write \`.dosu/audit.json\`, then invoke only the task IDs the user chooses:
|
|
60564
|
+
|
|
60565
|
+
\`\`\`bash
|
|
60566
|
+
dosu audit --tasks <comma-separated-task-ids> --json
|
|
60567
|
+
\`\`\`
|
|
60568
|
+
|
|
60569
|
+
The coding agent performs triage; Dosu cloud generates docs and opens the PR.
|
|
60570
|
+
`,
|
|
60571
|
+
executable: false
|
|
60572
|
+
}
|
|
60573
|
+
]
|
|
60574
|
+
}
|
|
60575
|
+
];
|
|
60576
|
+
});
|
|
60577
|
+
|
|
60578
|
+
// src/commands/skill.ts
|
|
60579
|
+
import {
|
|
60580
|
+
cpSync,
|
|
60581
|
+
existsSync as existsSync19,
|
|
60582
|
+
lstatSync as lstatSync2,
|
|
60583
|
+
mkdirSync as mkdirSync11,
|
|
60584
|
+
readFileSync as readFileSync19,
|
|
60585
|
+
rmSync as rmSync5,
|
|
60586
|
+
symlinkSync,
|
|
60587
|
+
writeFileSync as writeFileSync12
|
|
60588
|
+
} from "node:fs";
|
|
60589
|
+
import { homedir as homedir8 } from "node:os";
|
|
60590
|
+
import { dirname as dirname10, join as join22, relative as relative3 } from "node:path";
|
|
60591
|
+
function skillAgentIDsForProviders(providerIDs) {
|
|
60592
|
+
return [
|
|
60593
|
+
...new Set(providerIDs.map((providerID) => SKILL_AGENT_BY_PROVIDER[providerID]).filter((agent) => Boolean(agent)))
|
|
60594
|
+
];
|
|
59807
60595
|
}
|
|
59808
|
-
function
|
|
60596
|
+
function isSkillAgentID(agent) {
|
|
60597
|
+
return SUPPORTED_SKILL_AGENTS.includes(agent);
|
|
60598
|
+
}
|
|
60599
|
+
function universalSkillsDir() {
|
|
60600
|
+
return join22(homedir8(), ".agents", "skills");
|
|
60601
|
+
}
|
|
60602
|
+
function linkedSkillsDir(agent) {
|
|
60603
|
+
if (agent === "claude-code") {
|
|
60604
|
+
const claudeConfigDir = process.env.CLAUDE_CONFIG_DIR?.trim() || join22(homedir8(), ".claude");
|
|
60605
|
+
return join22(claudeConfigDir, "skills");
|
|
60606
|
+
}
|
|
60607
|
+
if (agent === "windsurf")
|
|
60608
|
+
return join22(homedir8(), ".codeium", "windsurf", "skills");
|
|
60609
|
+
return null;
|
|
60610
|
+
}
|
|
60611
|
+
function skillInstallTargetForProvider(providerID) {
|
|
60612
|
+
const agentID = SKILL_AGENT_BY_PROVIDER[providerID];
|
|
60613
|
+
if (!agentID)
|
|
60614
|
+
return null;
|
|
60615
|
+
const linked = linkedSkillsDir(agentID);
|
|
60616
|
+
if (linked)
|
|
60617
|
+
return { path: join22(linked, SKILL_NAME), symlink: true };
|
|
60618
|
+
return { path: join22(universalSkillsDir(), SKILL_NAME), symlink: false };
|
|
60619
|
+
}
|
|
60620
|
+
function installStatePath() {
|
|
60621
|
+
return join22(getConfigDir(), INSTALL_STATE_FILENAME);
|
|
60622
|
+
}
|
|
60623
|
+
function readSkillInstallState() {
|
|
59809
60624
|
try {
|
|
59810
|
-
const path =
|
|
60625
|
+
const path = installStatePath();
|
|
59811
60626
|
if (!existsSync19(path))
|
|
59812
60627
|
return null;
|
|
59813
60628
|
const data = JSON.parse(readFileSync19(path, "utf-8"));
|
|
59814
|
-
if (typeof data
|
|
59815
|
-
return data;
|
|
60629
|
+
if (typeof data?.version === "string" && Array.isArray(data.agents) && data.agents.every((agent) => typeof agent === "string") && typeof data.installedAt === "number") {
|
|
60630
|
+
return { version: data.version, agents: data.agents, installedAt: data.installedAt };
|
|
59816
60631
|
}
|
|
59817
60632
|
return null;
|
|
59818
60633
|
} catch {
|
|
59819
60634
|
return null;
|
|
59820
60635
|
}
|
|
59821
60636
|
}
|
|
59822
|
-
function
|
|
60637
|
+
function writeSkillInstallState(state) {
|
|
59823
60638
|
try {
|
|
59824
60639
|
const dir = getConfigDir();
|
|
59825
|
-
if (!existsSync19(dir))
|
|
60640
|
+
if (!existsSync19(dir))
|
|
59826
60641
|
mkdirSync11(dir, { recursive: true, mode: 448 });
|
|
59827
|
-
}
|
|
59828
|
-
|
|
59829
|
-
|
|
59830
|
-
}
|
|
59831
|
-
function clearInstalledSha() {
|
|
59832
|
-
const cache = readSkillCache();
|
|
59833
|
-
if (cache)
|
|
59834
|
-
writeSkillCache({ ...cache, installedSha: "" });
|
|
59835
|
-
}
|
|
59836
|
-
async function fetchLatestSha() {
|
|
59837
|
-
const controller = new AbortController;
|
|
59838
|
-
const timeout = setTimeout(() => controller.abort(), FETCH_TIMEOUT_MS2);
|
|
59839
|
-
try {
|
|
59840
|
-
const resp = await fetch(GITHUB_API_URL, {
|
|
59841
|
-
signal: controller.signal,
|
|
59842
|
-
headers: {
|
|
59843
|
-
"User-Agent": `dosu-cli/${VERSION}`,
|
|
59844
|
-
Accept: "application/vnd.github+json"
|
|
59845
|
-
}
|
|
59846
|
-
});
|
|
59847
|
-
if (!resp.ok)
|
|
59848
|
-
return null;
|
|
59849
|
-
const data = await resp.json();
|
|
59850
|
-
const sha = data.sha;
|
|
59851
|
-
return typeof sha === "string" ? sha : null;
|
|
59852
|
-
} catch {
|
|
59853
|
-
return null;
|
|
59854
|
-
} finally {
|
|
59855
|
-
clearTimeout(timeout);
|
|
60642
|
+
writeFileSync12(installStatePath(), JSON.stringify(state), { mode: 384 });
|
|
60643
|
+
} catch (err) {
|
|
60644
|
+
logger.debug("skill", `Could not record skill install state: ${err}`);
|
|
59856
60645
|
}
|
|
59857
60646
|
}
|
|
59858
|
-
function
|
|
59859
|
-
|
|
59860
|
-
${import_picocolors26.default.yellow(" Dosu skill update available")}
|
|
59861
|
-
` + `${import_picocolors26.default.dim(' Run "dosu skill update" to upgrade')}
|
|
59862
|
-
`;
|
|
59863
|
-
console.error(msg);
|
|
60647
|
+
function clearSkillInstallState() {
|
|
60648
|
+
rmSync5(installStatePath(), { force: true });
|
|
59864
60649
|
}
|
|
59865
|
-
function
|
|
60650
|
+
function pruneLegacySkillLock() {
|
|
60651
|
+
const lockPath = join22(homedir8(), ".agents", ".skill-lock.json");
|
|
59866
60652
|
try {
|
|
59867
|
-
|
|
59868
|
-
|
|
59869
|
-
|
|
59870
|
-
|
|
59871
|
-
|
|
59872
|
-
|
|
59873
|
-
|
|
59874
|
-
|
|
59875
|
-
|
|
59876
|
-
|
|
59877
|
-
|
|
59878
|
-
|
|
59879
|
-
|
|
59880
|
-
|
|
59881
|
-
|
|
59882
|
-
}
|
|
59883
|
-
}).catch((err) => {
|
|
59884
|
-
logger.error("skill-update-check", `Background fetch failed: ${err}`);
|
|
59885
|
-
});
|
|
59886
|
-
}
|
|
60653
|
+
if (!existsSync19(lockPath))
|
|
60654
|
+
return [];
|
|
60655
|
+
const lock = JSON.parse(readFileSync19(lockPath, "utf-8"));
|
|
60656
|
+
const skills = lock?.skills;
|
|
60657
|
+
if (!skills || typeof skills !== "object")
|
|
60658
|
+
return [];
|
|
60659
|
+
const legacy = Object.entries(skills).filter(([, entry]) => entry?.source === LEGACY_SKILL_SOURCE).map(([name]) => name);
|
|
60660
|
+
if (legacy.length === 0)
|
|
60661
|
+
return [];
|
|
60662
|
+
for (const name of legacy)
|
|
60663
|
+
delete skills[name];
|
|
60664
|
+
writeFileSync12(lockPath, `${JSON.stringify(lock, null, 2)}
|
|
60665
|
+
`);
|
|
60666
|
+
logger.debug("skill", `Removed legacy lock entries: ${legacy.join(", ")}`);
|
|
60667
|
+
return legacy;
|
|
59887
60668
|
} catch (err) {
|
|
59888
|
-
logger.
|
|
60669
|
+
logger.debug("skill", `Could not read legacy skill lock: ${err}`);
|
|
60670
|
+
return [];
|
|
59889
60671
|
}
|
|
59890
60672
|
}
|
|
59891
|
-
|
|
59892
|
-
|
|
59893
|
-
|
|
59894
|
-
|
|
59895
|
-
|
|
59896
|
-
|
|
59897
|
-
});
|
|
59898
|
-
|
|
59899
|
-
// src/commands/skill.ts
|
|
59900
|
-
import { exec as exec2, execSync as execSync2 } from "node:child_process";
|
|
59901
|
-
import { homedir as homedir8 } from "node:os";
|
|
59902
|
-
import { join as join23 } from "node:path";
|
|
59903
|
-
function skillAgentIDsForProviders(providerIDs) {
|
|
59904
|
-
return [
|
|
59905
|
-
...new Set(providerIDs.map((providerID) => SKILL_AGENT_BY_PROVIDER[providerID]).filter((agent) => Boolean(agent)))
|
|
59906
|
-
];
|
|
59907
|
-
}
|
|
59908
|
-
function skillInstallTargetForProvider(providerID) {
|
|
59909
|
-
const agentID = SKILL_AGENT_BY_PROVIDER[providerID];
|
|
59910
|
-
if (!agentID)
|
|
59911
|
-
return null;
|
|
59912
|
-
if (agentID === "claude-code") {
|
|
59913
|
-
const claudeConfigDir = process.env.CLAUDE_CONFIG_DIR?.trim() || join23(homedir8(), ".claude");
|
|
59914
|
-
return { path: join23(claudeConfigDir, "skills", SKILL_NAME), symlink: true };
|
|
60673
|
+
function pathExists(path) {
|
|
60674
|
+
try {
|
|
60675
|
+
lstatSync2(path);
|
|
60676
|
+
return true;
|
|
60677
|
+
} catch {
|
|
60678
|
+
return false;
|
|
59915
60679
|
}
|
|
59916
|
-
|
|
59917
|
-
|
|
59918
|
-
|
|
59919
|
-
|
|
59920
|
-
|
|
60680
|
+
}
|
|
60681
|
+
function writeSkillDir(skill, dir) {
|
|
60682
|
+
rmSync5(dir, { recursive: true, force: true });
|
|
60683
|
+
for (const file of skill.files) {
|
|
60684
|
+
const target = join22(dir, ...file.path.split("/"));
|
|
60685
|
+
mkdirSync11(dirname10(target), { recursive: true });
|
|
60686
|
+
writeFileSync12(target, file.content, { mode: file.executable ? 493 : 420 });
|
|
59921
60687
|
}
|
|
59922
|
-
return {
|
|
59923
|
-
path: join23(homedir8(), ".agents", "skills", SKILL_NAME),
|
|
59924
|
-
symlink: false
|
|
59925
|
-
};
|
|
59926
60688
|
}
|
|
59927
|
-
function
|
|
59928
|
-
|
|
59929
|
-
|
|
60689
|
+
function linkSkillDir(linkPath, targetDir) {
|
|
60690
|
+
mkdirSync11(dirname10(linkPath), { recursive: true });
|
|
60691
|
+
rmSync5(linkPath, { recursive: true, force: true });
|
|
60692
|
+
try {
|
|
60693
|
+
symlinkSync(relative3(dirname10(linkPath), targetDir), linkPath, "dir");
|
|
60694
|
+
return "symlink";
|
|
60695
|
+
} catch (err) {
|
|
60696
|
+
logger.debug("skill", `Symlink failed for ${linkPath}, copying instead: ${err}`);
|
|
60697
|
+
cpSync(targetDir, linkPath, { recursive: true });
|
|
60698
|
+
return "copy";
|
|
60699
|
+
}
|
|
59930
60700
|
}
|
|
59931
|
-
function
|
|
59932
|
-
|
|
59933
|
-
|
|
59934
|
-
|
|
59935
|
-
|
|
59936
|
-
else
|
|
59937
|
-
resolve();
|
|
59938
|
-
});
|
|
59939
|
-
});
|
|
60701
|
+
function removeSkillDir(dir) {
|
|
60702
|
+
if (!pathExists(dir))
|
|
60703
|
+
return false;
|
|
60704
|
+
rmSync5(dir, { recursive: true, force: true });
|
|
60705
|
+
return true;
|
|
59940
60706
|
}
|
|
59941
|
-
|
|
59942
|
-
const
|
|
59943
|
-
if (
|
|
59944
|
-
logger.debug("skill", "No selected
|
|
60707
|
+
function installBundledSkills(agentIDs) {
|
|
60708
|
+
const agents = agentIDs.filter(isSkillAgentID);
|
|
60709
|
+
if (agents.length === 0) {
|
|
60710
|
+
logger.debug("skill", "No selected agents support the Dosu skill");
|
|
59945
60711
|
return { success: true };
|
|
59946
60712
|
}
|
|
59947
60713
|
try {
|
|
59948
|
-
const
|
|
59949
|
-
|
|
59950
|
-
|
|
59951
|
-
|
|
59952
|
-
|
|
60714
|
+
const legacy = pruneLegacySkillLock();
|
|
60715
|
+
const bundledNames = new Set(BUNDLED_SKILLS.map((skill) => skill.name));
|
|
60716
|
+
const linkDirs = [
|
|
60717
|
+
...new Set(agents.map(linkedSkillsDir).filter((dir) => !!dir))
|
|
60718
|
+
];
|
|
60719
|
+
for (const name of legacy) {
|
|
60720
|
+
if (bundledNames.has(name))
|
|
60721
|
+
continue;
|
|
60722
|
+
for (const dir of [universalSkillsDir(), ...linkDirs])
|
|
60723
|
+
removeSkillDir(join22(dir, name));
|
|
60724
|
+
}
|
|
60725
|
+
const paths = [];
|
|
60726
|
+
for (const skill of BUNDLED_SKILLS) {
|
|
60727
|
+
const universal = join22(universalSkillsDir(), skill.name);
|
|
60728
|
+
writeSkillDir(skill, universal);
|
|
60729
|
+
paths.push(universal);
|
|
60730
|
+
for (const dir of linkDirs) {
|
|
60731
|
+
const linkPath = join22(dir, skill.name);
|
|
60732
|
+
linkSkillDir(linkPath, universal);
|
|
60733
|
+
paths.push(linkPath);
|
|
60734
|
+
}
|
|
60735
|
+
}
|
|
60736
|
+
const previous = readSkillInstallState();
|
|
60737
|
+
writeSkillInstallState({
|
|
60738
|
+
version: VERSION,
|
|
60739
|
+
agents: [...new Set([...previous?.agents ?? [], ...agents])],
|
|
60740
|
+
installedAt: Date.now()
|
|
60741
|
+
});
|
|
60742
|
+
rmSync5(join22(getConfigDir(), LEGACY_CACHE_FILENAME), { force: true });
|
|
60743
|
+
logger.info("skill", `Installed bundled skills v${VERSION} for ${agents.join(", ")}`);
|
|
60744
|
+
return { success: true, version: VERSION, paths };
|
|
59953
60745
|
} catch (err) {
|
|
59954
60746
|
logger.error("skill", `Failed to install skill: ${err}`);
|
|
59955
60747
|
return { success: false };
|
|
59956
60748
|
}
|
|
59957
|
-
const sha = await fetchLatestSha();
|
|
59958
|
-
if (sha) {
|
|
59959
|
-
writeSkillCache({
|
|
59960
|
-
lastCheck: Date.now(),
|
|
59961
|
-
latestSha: sha,
|
|
59962
|
-
installedSha: sha
|
|
59963
|
-
});
|
|
59964
|
-
return { success: true, sha };
|
|
59965
|
-
}
|
|
59966
|
-
logger.debug("skill", "Skill installed but could not fetch latest SHA");
|
|
59967
|
-
return { success: true };
|
|
59968
60749
|
}
|
|
59969
|
-
function
|
|
59970
|
-
|
|
59971
|
-
|
|
59972
|
-
|
|
59973
|
-
|
|
59974
|
-
|
|
59975
|
-
|
|
59976
|
-
|
|
59977
|
-
|
|
59978
|
-
|
|
59979
|
-
|
|
59980
|
-
|
|
59981
|
-
|
|
59982
|
-
|
|
59983
|
-
|
|
59984
|
-
|
|
59985
|
-
|
|
59986
|
-
if (entry.source !== SKILL_REPO || typeof entry.name !== "string")
|
|
59987
|
-
continue;
|
|
59988
|
-
if (!SAFE_SKILL_NAME.test(entry.name)) {
|
|
59989
|
-
logger.warn("skill", `Skipping skill with an unsupported name: ${entry.name}`);
|
|
59990
|
-
continue;
|
|
60750
|
+
async function installSkill(providerIDs) {
|
|
60751
|
+
const agents = providerIDs === undefined ? [...SUPPORTED_SKILL_AGENTS] : skillAgentIDsForProviders(providerIDs);
|
|
60752
|
+
return installBundledSkills(agents);
|
|
60753
|
+
}
|
|
60754
|
+
function removeSkills() {
|
|
60755
|
+
const legacy = pruneLegacySkillLock();
|
|
60756
|
+
const names = new Set([...BUNDLED_SKILLS.map((skill) => skill.name), ...legacy]);
|
|
60757
|
+
const dirs = [
|
|
60758
|
+
universalSkillsDir(),
|
|
60759
|
+
...new Set(SUPPORTED_SKILL_AGENTS.map(linkedSkillsDir).filter((dir) => !!dir))
|
|
60760
|
+
];
|
|
60761
|
+
const removed = [];
|
|
60762
|
+
for (const dir of dirs) {
|
|
60763
|
+
for (const name of names) {
|
|
60764
|
+
const path = join22(dir, name);
|
|
60765
|
+
if (removeSkillDir(path))
|
|
60766
|
+
removed.push(path);
|
|
59991
60767
|
}
|
|
59992
|
-
names.push(entry.name);
|
|
59993
60768
|
}
|
|
59994
|
-
|
|
60769
|
+
clearSkillInstallState();
|
|
60770
|
+
rmSync5(join22(getConfigDir(), LEGACY_CACHE_FILENAME), { force: true });
|
|
60771
|
+
return removed;
|
|
60772
|
+
}
|
|
60773
|
+
function printPaths(paths) {
|
|
60774
|
+
for (const path of paths)
|
|
60775
|
+
console.log(import_picocolors26.default.dim(` ${path}`));
|
|
59995
60776
|
}
|
|
59996
60777
|
function skillCommand() {
|
|
59997
|
-
const cmd = new Command("skill").description("Manage the Dosu agent
|
|
59998
|
-
cmd.command("install").description("Install the Dosu
|
|
59999
|
-
console.log(`Installing skills
|
|
60778
|
+
const cmd = new Command("skill").description("Manage the Dosu agent skills bundled with the CLI");
|
|
60779
|
+
cmd.command("install").description("Install the bundled Dosu skills for AI coding agents").action(async () => {
|
|
60780
|
+
console.log(`Installing Dosu skills (v${VERSION})...`);
|
|
60000
60781
|
const result = await installSkill();
|
|
60001
60782
|
if (result.success) {
|
|
60002
|
-
|
|
60783
|
+
printPaths(result.paths ?? []);
|
|
60784
|
+
console.log(import_picocolors26.default.green(`
|
|
60003
60785
|
✓ Skills installed successfully.`));
|
|
60004
60786
|
} else {
|
|
60005
|
-
console.error(
|
|
60006
|
-
Failed to install skill.
|
|
60787
|
+
console.error(import_picocolors26.default.red(`
|
|
60788
|
+
Failed to install skill. Run with --debug for details.`));
|
|
60007
60789
|
process.exit(1);
|
|
60008
60790
|
}
|
|
60009
60791
|
});
|
|
60010
60792
|
cmd.command("remove").description("Remove the Dosu skills").action(() => {
|
|
60011
|
-
const installed = installedSkillNames();
|
|
60012
|
-
if (installed?.length === 0) {
|
|
60013
|
-
console.log(`No skills from ${SKILL_REPO} are installed.`);
|
|
60014
|
-
return;
|
|
60015
|
-
}
|
|
60016
|
-
const targets = installed ?? [SKILL_NAME];
|
|
60017
|
-
console.log(`Removing skills from ${SKILL_REPO}...`);
|
|
60018
60793
|
try {
|
|
60019
|
-
|
|
60020
|
-
|
|
60021
|
-
|
|
60022
|
-
|
|
60023
|
-
|
|
60794
|
+
const removed = removeSkills();
|
|
60795
|
+
if (removed.length === 0) {
|
|
60796
|
+
console.log("No Dosu skills are installed.");
|
|
60797
|
+
return;
|
|
60798
|
+
}
|
|
60799
|
+
console.log("Removing Dosu skills...");
|
|
60800
|
+
printPaths(removed);
|
|
60801
|
+
console.log(import_picocolors26.default.green(`
|
|
60024
60802
|
✓ Skills removed.`));
|
|
60025
|
-
} catch {
|
|
60026
|
-
|
|
60803
|
+
} catch (err) {
|
|
60804
|
+
logger.error("skill", `Failed to remove skills: ${err}`);
|
|
60805
|
+
console.error(import_picocolors26.default.red(`
|
|
60027
60806
|
Failed to remove skills.`));
|
|
60028
60807
|
process.exit(1);
|
|
60029
60808
|
}
|
|
60030
60809
|
});
|
|
60031
|
-
cmd.command("update").description("
|
|
60032
|
-
console.log(`Updating skills
|
|
60810
|
+
cmd.command("update").description("Rewrite the Dosu skills from this CLI version (upgrade the CLI for newer skills)").action(async () => {
|
|
60811
|
+
console.log(`Updating Dosu skills to the copy bundled with v${VERSION}...`);
|
|
60033
60812
|
const result = await installSkill();
|
|
60034
60813
|
if (!result.success) {
|
|
60035
|
-
console.error(
|
|
60814
|
+
console.error(import_picocolors26.default.red(`
|
|
60036
60815
|
Failed to update skill.`));
|
|
60037
60816
|
process.exit(1);
|
|
60038
60817
|
}
|
|
60039
|
-
|
|
60818
|
+
printPaths(result.paths ?? []);
|
|
60819
|
+
console.log(import_picocolors26.default.green(`
|
|
60040
60820
|
✓ Skills updated.`));
|
|
60821
|
+
console.log(import_picocolors26.default.dim(" Skills ship with the CLI; run `dosu upgrade` to get newer ones."));
|
|
60041
60822
|
});
|
|
60042
60823
|
return cmd;
|
|
60043
60824
|
}
|
|
60044
|
-
var
|
|
60825
|
+
var import_picocolors26, SKILL_NAME = "dosu", LEGACY_SKILL_SOURCE = "dosu-ai/dosu-skill", INSTALL_STATE_FILENAME = "skill-install.json", LEGACY_CACHE_FILENAME = "skill-update-check.json", SUPPORTED_SKILL_AGENTS, SKILL_AGENT_BY_PROVIDER;
|
|
60045
60826
|
var init_skill = __esm(() => {
|
|
60046
60827
|
init_commander();
|
|
60828
|
+
init_config();
|
|
60047
60829
|
init_logger();
|
|
60048
|
-
|
|
60049
|
-
|
|
60050
|
-
SAFE_SKILL_NAME = /^[a-zA-Z0-9][a-zA-Z0-9._-]*$/;
|
|
60830
|
+
init_skills();
|
|
60831
|
+
import_picocolors26 = __toESM(require_picocolors(), 1);
|
|
60051
60832
|
SUPPORTED_SKILL_AGENTS = [
|
|
60052
60833
|
"claude-code",
|
|
60053
60834
|
"cursor",
|
|
@@ -60080,7 +60861,7 @@ var init_skill = __esm(() => {
|
|
|
60080
60861
|
function requireConfig11() {
|
|
60081
60862
|
const cfg = requireLoginConfig();
|
|
60082
60863
|
if (!cfg.active_account?.target?.org_id) {
|
|
60083
|
-
console.error(
|
|
60864
|
+
console.error(import_picocolors27.default.red("Missing org config. Run 'dosu setup' to reconfigure."));
|
|
60084
60865
|
process.exit(1);
|
|
60085
60866
|
}
|
|
60086
60867
|
return cfg;
|
|
@@ -60090,7 +60871,7 @@ function rejectWebOnlyProvider(provider, json) {
|
|
|
60090
60871
|
if (json) {
|
|
60091
60872
|
printResult({ provider, cli_supported: false, connect_via: "web", url }, { json: true });
|
|
60092
60873
|
} else {
|
|
60093
|
-
console.error(
|
|
60874
|
+
console.error(import_picocolors27.default.yellow(`Connecting '${provider}' sources is web-only for now. Open ${url}, add the source ` + `under Data Sources, then re-run 'dosu sources list'.`));
|
|
60094
60875
|
}
|
|
60095
60876
|
process.exit(1);
|
|
60096
60877
|
}
|
|
@@ -60109,7 +60890,7 @@ function sourcesCommand() {
|
|
|
60109
60890
|
}
|
|
60110
60891
|
const list = dataSources ?? [];
|
|
60111
60892
|
if (list.length === 0) {
|
|
60112
|
-
console.log(
|
|
60893
|
+
console.log(import_picocolors27.default.dim("No data sources connected."));
|
|
60113
60894
|
return;
|
|
60114
60895
|
}
|
|
60115
60896
|
printTable(["ID", "Name", "Provider", "Created"], list.map((ds) => [
|
|
@@ -60128,7 +60909,7 @@ function sourcesCommand() {
|
|
|
60128
60909
|
return;
|
|
60129
60910
|
}
|
|
60130
60911
|
if (!ds) {
|
|
60131
|
-
console.log(
|
|
60912
|
+
console.log(import_picocolors27.default.dim("Data source not found."));
|
|
60132
60913
|
return;
|
|
60133
60914
|
}
|
|
60134
60915
|
printInfo([
|
|
@@ -60147,7 +60928,7 @@ function sourcesCommand() {
|
|
|
60147
60928
|
printResult({ success: true, id }, opts);
|
|
60148
60929
|
return;
|
|
60149
60930
|
}
|
|
60150
|
-
console.log(
|
|
60931
|
+
console.log(import_picocolors27.default.green(`Data source sync triggered for ${id.slice(0, 8)}.`));
|
|
60151
60932
|
});
|
|
60152
60933
|
cmd.command("update").description("Update a data source").argument("<id>", "Data source ID").option("--name <name>", "New name").option("--description <desc>", "New description").option("--json", "Output as JSON").action(async (id, opts) => {
|
|
60153
60934
|
if (opts.name === undefined && opts.description === undefined) {
|
|
@@ -60164,7 +60945,7 @@ function sourcesCommand() {
|
|
|
60164
60945
|
printResult(result, opts);
|
|
60165
60946
|
return;
|
|
60166
60947
|
}
|
|
60167
|
-
console.log(
|
|
60948
|
+
console.log(import_picocolors27.default.green("Data source updated."));
|
|
60168
60949
|
});
|
|
60169
60950
|
cmd.command("delete").description("Delete a data source").argument("<id>", "Data source ID").option("--json", "Output as JSON").action(async (id, opts) => {
|
|
60170
60951
|
const cfg = requireConfig11();
|
|
@@ -60174,7 +60955,7 @@ function sourcesCommand() {
|
|
|
60174
60955
|
printResult({ success: true, id }, opts);
|
|
60175
60956
|
return;
|
|
60176
60957
|
}
|
|
60177
|
-
console.log(
|
|
60958
|
+
console.log(import_picocolors27.default.green("Data source deleted."));
|
|
60178
60959
|
});
|
|
60179
60960
|
cmd.command("connect").description("Install or update a provider integration (currently GitHub) via the browser").argument("[provider]", "Provider to connect (github)", "github").option("--json", "Emit machine-readable NDJSON progress events").option("--timeout <seconds>", "Seconds to wait for the browser install to complete", String(CONNECT_TIMEOUT_DEFAULT_SECONDS)).option("--no-open", "Print the URL without opening a browser").action(async (provider, opts) => {
|
|
60180
60961
|
const providerName = provider.toLowerCase();
|
|
@@ -60202,14 +60983,14 @@ function sourcesCommand() {
|
|
|
60202
60983
|
}));
|
|
60203
60984
|
} else {
|
|
60204
60985
|
console.log(`Open this URL to install or update the Dosu GitHub App:
|
|
60205
|
-
${
|
|
60986
|
+
${import_picocolors27.default.cyan(url)}`);
|
|
60206
60987
|
if (opts.open !== false) {
|
|
60207
60988
|
try {
|
|
60208
60989
|
const open = await Promise.resolve().then(() => (init_open(), {}));
|
|
60209
60990
|
await open_default(url);
|
|
60210
60991
|
} catch {}
|
|
60211
60992
|
}
|
|
60212
|
-
console.log(
|
|
60993
|
+
console.log(import_picocolors27.default.dim("Waiting for the install to complete..."));
|
|
60213
60994
|
}
|
|
60214
60995
|
const timedOut = new Promise((resolve) => {
|
|
60215
60996
|
timeoutId = setTimeout(() => resolve(null), timeoutSeconds * 1000);
|
|
@@ -60219,7 +61000,7 @@ function sourcesCommand() {
|
|
|
60219
61000
|
if (opts.json) {
|
|
60220
61001
|
console.log(JSON.stringify({ event: "timeout", timeout_seconds: timeoutSeconds }));
|
|
60221
61002
|
} else {
|
|
60222
|
-
console.error(
|
|
61003
|
+
console.error(import_picocolors27.default.red(`Timed out after ${timeoutSeconds}s. Finish the install in the browser, then re-run 'dosu sources connect github'.`));
|
|
60223
61004
|
}
|
|
60224
61005
|
process.exit(1);
|
|
60225
61006
|
return;
|
|
@@ -60235,14 +61016,14 @@ function sourcesCommand() {
|
|
|
60235
61016
|
}));
|
|
60236
61017
|
return;
|
|
60237
61018
|
}
|
|
60238
|
-
console.log(
|
|
61019
|
+
console.log(import_picocolors27.default.green(`GitHub App connected (installation ${result.installation_id}).`));
|
|
60239
61020
|
if (newRepositories.length > 0) {
|
|
60240
61021
|
for (const repo of newRepositories) {
|
|
60241
61022
|
console.log(` ${repo.slug}`);
|
|
60242
61023
|
}
|
|
60243
|
-
console.log(
|
|
61024
|
+
console.log(import_picocolors27.default.dim("Next: dosu sources create github --repo <owner/name> --library <library-id>"));
|
|
60244
61025
|
} else {
|
|
60245
|
-
console.log(
|
|
61026
|
+
console.log(import_picocolors27.default.dim("No new repositories visible yet — GitHub may still be syncing. " + "Re-run 'dosu sources connect github' or check 'dosu sources list' shortly."));
|
|
60246
61027
|
}
|
|
60247
61028
|
} finally {
|
|
60248
61029
|
clearTimeout(timeoutId);
|
|
@@ -60259,7 +61040,7 @@ function sourcesCommand() {
|
|
|
60259
61040
|
const orgID = cfg.active_account.target.org_id;
|
|
60260
61041
|
const libraryID = opts.library ?? cfg.active_account?.target?.space_id;
|
|
60261
61042
|
if (!libraryID) {
|
|
60262
|
-
console.error(
|
|
61043
|
+
console.error(import_picocolors27.default.red("No library specified and no active library. Pass --library <id>."));
|
|
60263
61044
|
process.exit(1);
|
|
60264
61045
|
return;
|
|
60265
61046
|
}
|
|
@@ -60267,12 +61048,12 @@ function sourcesCommand() {
|
|
|
60267
61048
|
const repos = await fetchListForOrg(client, orgID);
|
|
60268
61049
|
const repo = repos.find((r) => r.slug.toLowerCase() === opts.repo.toLowerCase());
|
|
60269
61050
|
if (!repo) {
|
|
60270
|
-
console.error(
|
|
61051
|
+
console.error(import_picocolors27.default.red(`Repository '${opts.repo}' is not visible to Dosu. Run ` + `'dosu sources connect github' to grant the GitHub App access, then retry.`));
|
|
60271
61052
|
process.exit(1);
|
|
60272
61053
|
return;
|
|
60273
61054
|
}
|
|
60274
61055
|
if (repo.is_fork === true) {
|
|
60275
|
-
console.error(
|
|
61056
|
+
console.error(import_picocolors27.default.red(`'${repo.slug}' is a fork and can't be synced.` + (repo.fork_parent_slug ? ` Connect '${repo.fork_parent_slug}' instead.` : "")));
|
|
60276
61057
|
process.exit(1);
|
|
60277
61058
|
return;
|
|
60278
61059
|
}
|
|
@@ -60296,14 +61077,14 @@ function sourcesCommand() {
|
|
|
60296
61077
|
dataSourceID: existingDataSources.get(repo.repository_id)
|
|
60297
61078
|
});
|
|
60298
61079
|
if (!created) {
|
|
60299
|
-
console.error(
|
|
61080
|
+
console.error(import_picocolors27.default.red("Could not create the data source. Check 'dosu logs --tail 50' for details."));
|
|
60300
61081
|
process.exit(1);
|
|
60301
61082
|
return;
|
|
60302
61083
|
}
|
|
60303
61084
|
const survivors = await verifyDataSourcesPersist(client, orgID, [created.data_source_id]);
|
|
60304
61085
|
if (survivors.dropped.size > 0) {
|
|
60305
61086
|
await deleteOrphanDeployment(client, created.deployment_id, repo.slug);
|
|
60306
|
-
console.error(
|
|
61087
|
+
console.error(import_picocolors27.default.red(`Dosu couldn't sync '${repo.slug}' (the GitHub App may not have access to it). ` + "Nothing was created."));
|
|
60307
61088
|
process.exit(1);
|
|
60308
61089
|
return;
|
|
60309
61090
|
}
|
|
@@ -60320,13 +61101,13 @@ function sourcesCommand() {
|
|
|
60320
61101
|
printResult(receipt, opts);
|
|
60321
61102
|
return;
|
|
60322
61103
|
}
|
|
60323
|
-
console.log(
|
|
60324
|
-
console.log(
|
|
60325
|
-
console.log(
|
|
61104
|
+
console.log(import_picocolors27.default.green(`Connected ${repo.slug} to library ${libraryID}.`));
|
|
61105
|
+
console.log(import_picocolors27.default.dim(` data source ${created.data_source_id}`));
|
|
61106
|
+
console.log(import_picocolors27.default.dim(` deployment ${created.deployment_id}`));
|
|
60326
61107
|
});
|
|
60327
61108
|
return cmd;
|
|
60328
61109
|
}
|
|
60329
|
-
var
|
|
61110
|
+
var import_picocolors27, CONNECT_TIMEOUT_DEFAULT_SECONDS = 600;
|
|
60330
61111
|
var init_sources = __esm(() => {
|
|
60331
61112
|
init_commander();
|
|
60332
61113
|
init_trpc();
|
|
@@ -60335,23 +61116,23 @@ var init_sources = __esm(() => {
|
|
|
60335
61116
|
init_auth();
|
|
60336
61117
|
init_confirmation();
|
|
60337
61118
|
init_output();
|
|
60338
|
-
|
|
61119
|
+
import_picocolors27 = __toESM(require_picocolors(), 1);
|
|
60339
61120
|
});
|
|
60340
61121
|
|
|
60341
61122
|
// src/telemetry/settings.ts
|
|
60342
61123
|
import { randomUUID as randomUUID4 } from "node:crypto";
|
|
60343
61124
|
import {
|
|
60344
61125
|
existsSync as existsSync20,
|
|
60345
|
-
lstatSync as
|
|
61126
|
+
lstatSync as lstatSync3,
|
|
60346
61127
|
mkdirSync as mkdirSync12,
|
|
60347
61128
|
readFileSync as readFileSync20,
|
|
60348
61129
|
renameSync as renameSync5,
|
|
60349
61130
|
unlinkSync as unlinkSync4,
|
|
60350
61131
|
writeFileSync as writeFileSync13
|
|
60351
61132
|
} from "node:fs";
|
|
60352
|
-
import { join as
|
|
61133
|
+
import { join as join23 } from "node:path";
|
|
60353
61134
|
function getTelemetrySettingsPath() {
|
|
60354
|
-
return
|
|
61135
|
+
return join23(getConfigDir(), TELEMETRY_SETTINGS_FILENAME);
|
|
60355
61136
|
}
|
|
60356
61137
|
function loadTelemetrySettings() {
|
|
60357
61138
|
return readTelemetrySettings().settings;
|
|
@@ -60407,7 +61188,7 @@ function readTelemetrySettings() {
|
|
|
60407
61188
|
const path = getTelemetrySettingsPath();
|
|
60408
61189
|
let file;
|
|
60409
61190
|
try {
|
|
60410
|
-
file =
|
|
61191
|
+
file = lstatSync3(path);
|
|
60411
61192
|
} catch (error) {
|
|
60412
61193
|
if (isErrorCode(error, "ENOENT")) {
|
|
60413
61194
|
return { status: "missing", settings: emptyTelemetrySettings() };
|
|
@@ -60567,7 +61348,7 @@ var init_telemetry2 = __esm(() => {
|
|
|
60567
61348
|
function requireConfig12() {
|
|
60568
61349
|
const cfg = requireLoginConfig();
|
|
60569
61350
|
if (!cfg.active_account?.target?.space_id) {
|
|
60570
|
-
console.error(
|
|
61351
|
+
console.error(import_picocolors28.default.red("Missing space config. Run 'dosu setup' to reconfigure."));
|
|
60571
61352
|
process.exit(1);
|
|
60572
61353
|
}
|
|
60573
61354
|
return cfg;
|
|
@@ -60618,7 +61399,7 @@ function threadsCommand() {
|
|
|
60618
61399
|
return;
|
|
60619
61400
|
}
|
|
60620
61401
|
if (!threads || threads.length === 0) {
|
|
60621
|
-
console.log(
|
|
61402
|
+
console.log(import_picocolors28.default.dim("No threads found."));
|
|
60622
61403
|
return;
|
|
60623
61404
|
}
|
|
60624
61405
|
printTable(["ID", "Title", "Status", "Created"], threads.map((t) => [
|
|
@@ -60643,10 +61424,10 @@ function threadsCommand() {
|
|
|
60643
61424
|
return;
|
|
60644
61425
|
}
|
|
60645
61426
|
if (!thread) {
|
|
60646
|
-
console.log(
|
|
61427
|
+
console.log(import_picocolors28.default.dim("Thread not found."));
|
|
60647
61428
|
return;
|
|
60648
61429
|
}
|
|
60649
|
-
console.log(
|
|
61430
|
+
console.log(import_picocolors28.default.bold(thread.generated_title ?? "(untitled thread)"));
|
|
60650
61431
|
printInfo([
|
|
60651
61432
|
["ID", thread.id],
|
|
60652
61433
|
["Created", formatDate(thread.created_at)],
|
|
@@ -60657,13 +61438,13 @@ function threadsCommand() {
|
|
|
60657
61438
|
if (messages && messages.length > 0) {
|
|
60658
61439
|
const allMessages = messages.flatMap((group) => group.messages);
|
|
60659
61440
|
console.log(`
|
|
60660
|
-
${
|
|
60661
|
-
console.log(
|
|
61441
|
+
${import_picocolors28.default.bold("Messages")} (${allMessages.length})`);
|
|
61442
|
+
console.log(import_picocolors28.default.dim("─".repeat(60)));
|
|
60662
61443
|
for (const msg of allMessages) {
|
|
60663
61444
|
const role = msg.author_role ?? "unknown";
|
|
60664
61445
|
const date = formatDate(msg.created_at);
|
|
60665
61446
|
console.log(`
|
|
60666
|
-
${
|
|
61447
|
+
${import_picocolors28.default.bold(role)} ${import_picocolors28.default.dim(date)}`);
|
|
60667
61448
|
if (msg.body) {
|
|
60668
61449
|
console.log(truncate(msg.body, 500));
|
|
60669
61450
|
}
|
|
@@ -60678,25 +61459,25 @@ ${import_picocolors29.default.bold(role)} ${import_picocolors29.default.dim(date
|
|
|
60678
61459
|
printResult({ success: true, id }, opts);
|
|
60679
61460
|
return;
|
|
60680
61461
|
}
|
|
60681
|
-
console.log(
|
|
61462
|
+
console.log(import_picocolors28.default.green(`Thread ${id.slice(0, 8)} archived.`));
|
|
60682
61463
|
});
|
|
60683
61464
|
return cmd;
|
|
60684
61465
|
}
|
|
60685
|
-
var
|
|
61466
|
+
var import_picocolors28;
|
|
60686
61467
|
var init_threads = __esm(() => {
|
|
60687
61468
|
init_commander();
|
|
60688
61469
|
init_trpc();
|
|
60689
61470
|
init_arguments();
|
|
60690
61471
|
init_auth();
|
|
60691
61472
|
init_output();
|
|
60692
|
-
|
|
61473
|
+
import_picocolors28 = __toESM(require_picocolors(), 1);
|
|
60693
61474
|
});
|
|
60694
61475
|
|
|
60695
61476
|
// src/commands/topics.ts
|
|
60696
61477
|
function requireConfig13() {
|
|
60697
61478
|
const cfg = requireLoginConfig();
|
|
60698
61479
|
if (!cfg.active_account?.target?.space_id) {
|
|
60699
|
-
console.error(
|
|
61480
|
+
console.error(import_picocolors29.default.red("Missing space config. Run 'dosu setup' to reconfigure."));
|
|
60700
61481
|
process.exit(1);
|
|
60701
61482
|
}
|
|
60702
61483
|
return cfg;
|
|
@@ -60706,7 +61487,7 @@ async function getKnowledgeStoreId3(client, spaceId) {
|
|
|
60706
61487
|
space_id: spaceId
|
|
60707
61488
|
});
|
|
60708
61489
|
if (!store) {
|
|
60709
|
-
console.error(
|
|
61490
|
+
console.error(import_picocolors29.default.red("No knowledge store found for this deployment."));
|
|
60710
61491
|
process.exit(1);
|
|
60711
61492
|
}
|
|
60712
61493
|
return store.id;
|
|
@@ -60725,7 +61506,7 @@ function topicsCommand() {
|
|
|
60725
61506
|
return;
|
|
60726
61507
|
}
|
|
60727
61508
|
if (!topics || topics.length === 0) {
|
|
60728
|
-
console.log(
|
|
61509
|
+
console.log(import_picocolors29.default.dim("No topics found."));
|
|
60729
61510
|
return;
|
|
60730
61511
|
}
|
|
60731
61512
|
printTable(["ID", "Name", "Description"], topics.map((t) => [
|
|
@@ -60750,7 +61531,7 @@ function topicsCommand() {
|
|
|
60750
61531
|
return;
|
|
60751
61532
|
}
|
|
60752
61533
|
if (!pages || pages.length === 0) {
|
|
60753
|
-
console.log(
|
|
61534
|
+
console.log(import_picocolors29.default.dim("No pages found with this topic."));
|
|
60754
61535
|
return;
|
|
60755
61536
|
}
|
|
60756
61537
|
printTable(["ID", "Title"], pages.map((p) => [
|
|
@@ -60760,14 +61541,14 @@ function topicsCommand() {
|
|
|
60760
61541
|
});
|
|
60761
61542
|
return cmd;
|
|
60762
61543
|
}
|
|
60763
|
-
var
|
|
61544
|
+
var import_picocolors29;
|
|
60764
61545
|
var init_topics = __esm(() => {
|
|
60765
61546
|
init_commander();
|
|
60766
61547
|
init_trpc();
|
|
60767
61548
|
init_arguments();
|
|
60768
61549
|
init_auth();
|
|
60769
61550
|
init_output();
|
|
60770
|
-
|
|
61551
|
+
import_picocolors29 = __toESM(require_picocolors(), 1);
|
|
60771
61552
|
});
|
|
60772
61553
|
|
|
60773
61554
|
// src/commands/upgrade.ts
|
|
@@ -60920,7 +61701,7 @@ Could not update Dosu automatically.`);
|
|
|
60920
61701
|
${plan.manualCommand}`);
|
|
60921
61702
|
return result.status && result.status > 0 ? result.status : 1;
|
|
60922
61703
|
}
|
|
60923
|
-
console.log(
|
|
61704
|
+
console.log(import_picocolors30.default.green(`
|
|
60924
61705
|
✓ Update command completed.`));
|
|
60925
61706
|
console.log('Run "dosu --version" to verify.');
|
|
60926
61707
|
return 0;
|
|
@@ -60940,8 +61721,7 @@ function newBinaryInvocation(channel, args, entrypoint = process.argv[1], execPa
|
|
|
60940
61721
|
function isInteractiveTerminal() {
|
|
60941
61722
|
return process.stdin.isTTY === true && process.stdout.isTTY === true;
|
|
60942
61723
|
}
|
|
60943
|
-
function setupAgentsWithNewBinary(channel, options) {
|
|
60944
|
-
const interactive = options.interactive ?? isInteractiveTerminal();
|
|
61724
|
+
function setupAgentsWithNewBinary(channel, interactive, options) {
|
|
60945
61725
|
const invocation = newBinaryInvocation(channel, postUpgradeArgs(interactive), options.entrypoint ?? process.argv[1]);
|
|
60946
61726
|
if (!invocation) {
|
|
60947
61727
|
console.error(SETUP_FALLBACK);
|
|
@@ -60964,18 +61744,21 @@ async function completeUpgrade(channel = INSTALL_CHANNEL, options = {}) {
|
|
|
60964
61744
|
const status = runUpgrade(channel, options);
|
|
60965
61745
|
if (status !== 0)
|
|
60966
61746
|
return status;
|
|
60967
|
-
|
|
60968
|
-
|
|
60969
|
-
|
|
60970
|
-
|
|
60971
|
-
|
|
60972
|
-
|
|
61747
|
+
const interactive = options.interactive ?? isInteractiveTerminal();
|
|
61748
|
+
if (!interactive) {
|
|
61749
|
+
console.log("Updating Dosu skills...");
|
|
61750
|
+
try {
|
|
61751
|
+
const result = await installSkill();
|
|
61752
|
+
if (result.success) {
|
|
61753
|
+
console.log(import_picocolors30.default.green("✓ Skills updated."));
|
|
61754
|
+
} else {
|
|
61755
|
+
console.error('Skills could not be refreshed. Run "dosu skill update" to retry.');
|
|
61756
|
+
}
|
|
61757
|
+
} catch {
|
|
60973
61758
|
console.error('Skills could not be refreshed. Run "dosu skill update" to retry.');
|
|
60974
61759
|
}
|
|
60975
|
-
} catch {
|
|
60976
|
-
console.error('Skills could not be refreshed. Run "dosu skill update" to retry.');
|
|
60977
61760
|
}
|
|
60978
|
-
setupAgentsWithNewBinary(channel, options);
|
|
61761
|
+
setupAgentsWithNewBinary(channel, interactive, options);
|
|
60979
61762
|
return 0;
|
|
60980
61763
|
}
|
|
60981
61764
|
function upgradeCommand() {
|
|
@@ -60985,11 +61768,11 @@ function upgradeCommand() {
|
|
|
60985
61768
|
process.exitCode = status;
|
|
60986
61769
|
});
|
|
60987
61770
|
}
|
|
60988
|
-
var
|
|
61771
|
+
var import_picocolors30, PACKAGE_NAME = "@dosu/cli", LATEST_PACKAGE, BREW_MANUAL_COMMAND = "brew upgrade dosu-ai/dosu/dosu", NPX_COMMAND = "npx -y @dosu/cli@latest", PROBE_TIMEOUT_MS = 5000, RELEASES_URL = "https://github.com/dosu-ai/dosu-cli/releases/latest", PACKAGE_MANAGERS, SETUP_FALLBACK = 'Run "dosu setup" to finish updating your AI agents.';
|
|
60989
61772
|
var init_upgrade = __esm(() => {
|
|
60990
61773
|
init_commander();
|
|
60991
61774
|
init_skill();
|
|
60992
|
-
|
|
61775
|
+
import_picocolors30 = __toESM(require_picocolors(), 1);
|
|
60993
61776
|
LATEST_PACKAGE = `${PACKAGE_NAME}@latest`;
|
|
60994
61777
|
PACKAGE_MANAGERS = {
|
|
60995
61778
|
npm: {
|
|
@@ -61114,7 +61897,7 @@ var init_antigravity = __esm(() => {
|
|
|
61114
61897
|
});
|
|
61115
61898
|
|
|
61116
61899
|
// src/mcp/providers/claude.ts
|
|
61117
|
-
import { join as
|
|
61900
|
+
import { join as join24 } from "node:path";
|
|
61118
61901
|
var ClaudeProvider = () => createJSONProvider({
|
|
61119
61902
|
providerName: "Claude Code",
|
|
61120
61903
|
providerID: "claude",
|
|
@@ -61123,24 +61906,24 @@ var ClaudeProvider = () => createJSONProvider({
|
|
|
61123
61906
|
paths: ["~/.claude"],
|
|
61124
61907
|
globalPath: "~/.claude.json",
|
|
61125
61908
|
topKey: "mcpServers",
|
|
61126
|
-
localConfigPath: (cwd) =>
|
|
61909
|
+
localConfigPath: (cwd) => join24(cwd, ".mcp.json")
|
|
61127
61910
|
});
|
|
61128
61911
|
var init_claude = __esm(() => {
|
|
61129
61912
|
init_base();
|
|
61130
61913
|
});
|
|
61131
61914
|
|
|
61132
61915
|
// src/mcp/providers/claude-desktop.ts
|
|
61133
|
-
import { join as
|
|
61916
|
+
import { join as join25 } from "node:path";
|
|
61134
61917
|
function configPath() {
|
|
61135
|
-
return
|
|
61918
|
+
return join25(appSupportDir(), "Claude", "claude_desktop_config.json");
|
|
61136
61919
|
}
|
|
61137
61920
|
var ClaudeDesktopProvider = () => ({
|
|
61138
61921
|
name: () => "Claude Desktop",
|
|
61139
61922
|
id: () => "claude-desktop",
|
|
61140
61923
|
supportsLocal: () => false,
|
|
61141
61924
|
priority: () => 2,
|
|
61142
|
-
detectPaths: () => [
|
|
61143
|
-
isInstalled: () => isInstalled([
|
|
61925
|
+
detectPaths: () => [join25(appSupportDir(), "Claude")],
|
|
61926
|
+
isInstalled: () => isInstalled([join25(appSupportDir(), "Claude")]),
|
|
61144
61927
|
globalConfigPath: () => configPath(),
|
|
61145
61928
|
isConfigured: () => isJSONKeyConfigured(configPath(), "mcpServers"),
|
|
61146
61929
|
install(cfg, global2) {
|
|
@@ -61167,14 +61950,14 @@ var init_claude_desktop = __esm(() => {
|
|
|
61167
61950
|
});
|
|
61168
61951
|
|
|
61169
61952
|
// src/mcp/providers/cline.ts
|
|
61170
|
-
import { join as
|
|
61171
|
-
var extensionDir = () =>
|
|
61953
|
+
import { join as join26 } from "node:path";
|
|
61954
|
+
var extensionDir = () => join26(appSupportDir(), "Code", "User", "globalStorage", "saoudrizwan.claude-dev"), ClineProvider = () => createJSONProvider({
|
|
61172
61955
|
providerName: "Cline",
|
|
61173
61956
|
providerID: "cline",
|
|
61174
61957
|
local: false,
|
|
61175
61958
|
priorityValue: 11,
|
|
61176
61959
|
paths: [extensionDir()],
|
|
61177
|
-
globalPath:
|
|
61960
|
+
globalPath: join26(extensionDir(), "settings", "cline_mcp_settings.json"),
|
|
61178
61961
|
topKey: "mcpServers",
|
|
61179
61962
|
buildServer: ({ url, headers }) => ({
|
|
61180
61963
|
url,
|
|
@@ -61189,7 +61972,7 @@ var init_cline = __esm(() => {
|
|
|
61189
61972
|
});
|
|
61190
61973
|
|
|
61191
61974
|
// src/mcp/providers/cline-cli.ts
|
|
61192
|
-
import { join as
|
|
61975
|
+
import { join as join27 } from "node:path";
|
|
61193
61976
|
function clineDir() {
|
|
61194
61977
|
return process.env.CLINE_DIR ?? expandHome("~/.cline");
|
|
61195
61978
|
}
|
|
@@ -61199,7 +61982,7 @@ var ClineCliProvider = () => createJSONProvider({
|
|
|
61199
61982
|
local: false,
|
|
61200
61983
|
priorityValue: 12,
|
|
61201
61984
|
paths: [clineDir()],
|
|
61202
|
-
globalPath:
|
|
61985
|
+
globalPath: join27(clineDir(), "data", "settings", "cline_mcp_settings.json"),
|
|
61203
61986
|
topKey: "mcpServers",
|
|
61204
61987
|
buildServer: ({ url, headers }) => ({
|
|
61205
61988
|
url,
|
|
@@ -61215,14 +61998,14 @@ var init_cline_cli = __esm(() => {
|
|
|
61215
61998
|
|
|
61216
61999
|
// src/mcp/providers/codex.ts
|
|
61217
62000
|
import { existsSync as existsSync21, readFileSync as readFileSync21 } from "node:fs";
|
|
61218
|
-
import { dirname as
|
|
62001
|
+
import { dirname as dirname11, join as join28 } from "node:path";
|
|
61219
62002
|
function codexHome3() {
|
|
61220
62003
|
return process.env.CODEX_HOME ?? expandHome("~/.codex");
|
|
61221
62004
|
}
|
|
61222
62005
|
function getConfigPath2(global2) {
|
|
61223
62006
|
if (global2)
|
|
61224
|
-
return
|
|
61225
|
-
return
|
|
62007
|
+
return join28(codexHome3(), "config.toml");
|
|
62008
|
+
return join28(process.cwd(), ".codex", "config.toml");
|
|
61226
62009
|
}
|
|
61227
62010
|
function readTOML(path) {
|
|
61228
62011
|
if (!existsSync21(path))
|
|
@@ -61302,14 +62085,14 @@ function projectConfigPaths() {
|
|
|
61302
62085
|
const chain = [];
|
|
61303
62086
|
for (let dir = cwd;; ) {
|
|
61304
62087
|
chain.push(dir);
|
|
61305
|
-
if (existsSync21(
|
|
62088
|
+
if (existsSync21(join28(dir, ".git")))
|
|
61306
62089
|
break;
|
|
61307
|
-
const parent =
|
|
62090
|
+
const parent = dirname11(dir);
|
|
61308
62091
|
if (parent === dir)
|
|
61309
|
-
return [
|
|
62092
|
+
return [join28(cwd, ".codex", "config.toml")];
|
|
61310
62093
|
dir = parent;
|
|
61311
62094
|
}
|
|
61312
|
-
return chain.reverse().map((dir) =>
|
|
62095
|
+
return chain.reverse().map((dir) => join28(dir, ".codex", "config.toml"));
|
|
61313
62096
|
}
|
|
61314
62097
|
function pruneLegacyRemoteEntry(path) {
|
|
61315
62098
|
if (!existsSync21(path))
|
|
@@ -61326,9 +62109,9 @@ var REMOTE_HTTP_KEY, CodexProvider = () => ({
|
|
|
61326
62109
|
priority: () => 8,
|
|
61327
62110
|
detectPaths: () => ["~/.codex"],
|
|
61328
62111
|
isInstalled: () => isInstalled(["~/.codex"]),
|
|
61329
|
-
globalConfigPath: () =>
|
|
62112
|
+
globalConfigPath: () => join28(codexHome3(), "config.toml"),
|
|
61330
62113
|
isConfigured: () => {
|
|
61331
|
-
const content = readTOML(
|
|
62114
|
+
const content = readTOML(join28(codexHome3(), "config.toml"));
|
|
61332
62115
|
return content.includes("[mcp_servers.dosu]");
|
|
61333
62116
|
},
|
|
61334
62117
|
install(cfg, global2) {
|
|
@@ -61359,10 +62142,10 @@ var init_codex = __esm(() => {
|
|
|
61359
62142
|
});
|
|
61360
62143
|
|
|
61361
62144
|
// src/mcp/providers/copilot.ts
|
|
61362
|
-
import { join as
|
|
62145
|
+
import { join as join29 } from "node:path";
|
|
61363
62146
|
function globalPath() {
|
|
61364
62147
|
if (process.env.XDG_CONFIG_HOME) {
|
|
61365
|
-
return
|
|
62148
|
+
return join29(process.env.XDG_CONFIG_HOME, "mcp-config.json");
|
|
61366
62149
|
}
|
|
61367
62150
|
return expandHome("~/.copilot/mcp-config.json");
|
|
61368
62151
|
}
|
|
@@ -61386,7 +62169,7 @@ var CopilotProvider = () => ({
|
|
|
61386
62169
|
};
|
|
61387
62170
|
installJSONServer(globalPath(), "mcpServers", server);
|
|
61388
62171
|
} else {
|
|
61389
|
-
const configPath =
|
|
62172
|
+
const configPath = join29(process.cwd(), ".vscode", "mcp.json");
|
|
61390
62173
|
const server = {
|
|
61391
62174
|
type: "http",
|
|
61392
62175
|
url,
|
|
@@ -61399,7 +62182,7 @@ var CopilotProvider = () => ({
|
|
|
61399
62182
|
if (global2) {
|
|
61400
62183
|
removeJSONServer(globalPath(), "mcpServers");
|
|
61401
62184
|
} else {
|
|
61402
|
-
const configPath =
|
|
62185
|
+
const configPath = join29(process.cwd(), ".vscode", "mcp.json");
|
|
61403
62186
|
removeJSONServer(configPath, "servers");
|
|
61404
62187
|
}
|
|
61405
62188
|
}
|
|
@@ -61410,7 +62193,7 @@ var init_copilot = __esm(() => {
|
|
|
61410
62193
|
});
|
|
61411
62194
|
|
|
61412
62195
|
// src/mcp/providers/cursor.ts
|
|
61413
|
-
import { join as
|
|
62196
|
+
import { join as join30 } from "node:path";
|
|
61414
62197
|
var CursorProvider = () => createJSONProvider({
|
|
61415
62198
|
providerName: "Cursor",
|
|
61416
62199
|
providerID: "cursor",
|
|
@@ -61423,14 +62206,14 @@ var CursorProvider = () => createJSONProvider({
|
|
|
61423
62206
|
url,
|
|
61424
62207
|
headers
|
|
61425
62208
|
}),
|
|
61426
|
-
localConfigPath: (cwd) =>
|
|
62209
|
+
localConfigPath: (cwd) => join30(cwd, ".cursor", "mcp.json")
|
|
61427
62210
|
});
|
|
61428
62211
|
var init_cursor = __esm(() => {
|
|
61429
62212
|
init_base();
|
|
61430
62213
|
});
|
|
61431
62214
|
|
|
61432
62215
|
// src/mcp/providers/factory.ts
|
|
61433
|
-
import { join as
|
|
62216
|
+
import { join as join31 } from "node:path";
|
|
61434
62217
|
var FactoryProvider = () => createJSONProvider({
|
|
61435
62218
|
providerName: "Factory",
|
|
61436
62219
|
providerID: "factory",
|
|
@@ -61439,14 +62222,14 @@ var FactoryProvider = () => createJSONProvider({
|
|
|
61439
62222
|
paths: ["~/.factory"],
|
|
61440
62223
|
globalPath: "~/.factory/mcp.json",
|
|
61441
62224
|
topKey: "mcpServers",
|
|
61442
|
-
localConfigPath: (cwd) =>
|
|
62225
|
+
localConfigPath: (cwd) => join31(cwd, ".factory", "mcp.json")
|
|
61443
62226
|
});
|
|
61444
62227
|
var init_factory = __esm(() => {
|
|
61445
62228
|
init_base();
|
|
61446
62229
|
});
|
|
61447
62230
|
|
|
61448
62231
|
// src/mcp/providers/gemini.ts
|
|
61449
|
-
import { join as
|
|
62232
|
+
import { join as join32 } from "node:path";
|
|
61450
62233
|
var GeminiProvider = () => createJSONProvider({
|
|
61451
62234
|
providerName: "Gemini CLI",
|
|
61452
62235
|
providerID: "gemini",
|
|
@@ -61455,7 +62238,7 @@ var GeminiProvider = () => createJSONProvider({
|
|
|
61455
62238
|
paths: ["~/.gemini"],
|
|
61456
62239
|
globalPath: "~/.gemini/settings.json",
|
|
61457
62240
|
topKey: "mcpServers",
|
|
61458
|
-
localConfigPath: (cwd) =>
|
|
62241
|
+
localConfigPath: (cwd) => join32(cwd, ".gemini", "settings.json")
|
|
61459
62242
|
});
|
|
61460
62243
|
var init_gemini = __esm(() => {
|
|
61461
62244
|
init_base();
|
|
@@ -61498,7 +62281,7 @@ var init_manual = __esm(() => {
|
|
|
61498
62281
|
|
|
61499
62282
|
// src/mcp/providers/mcporter.ts
|
|
61500
62283
|
import { existsSync as existsSync22 } from "node:fs";
|
|
61501
|
-
import { join as
|
|
62284
|
+
import { join as join33 } from "node:path";
|
|
61502
62285
|
function resolveGlobalConfigPath() {
|
|
61503
62286
|
const jsonPath = expandHome("~/.mcporter/mcporter.json");
|
|
61504
62287
|
if (existsSync22(jsonPath))
|
|
@@ -61518,7 +62301,7 @@ var MCPorterProvider = () => ({
|
|
|
61518
62301
|
globalConfigPath: () => resolveGlobalConfigPath(),
|
|
61519
62302
|
isConfigured: () => isJSONKeyConfigured(resolveGlobalConfigPath(), "mcpServers"),
|
|
61520
62303
|
install(cfg, global2) {
|
|
61521
|
-
const configPath = global2 ? resolveGlobalConfigPath() :
|
|
62304
|
+
const configPath = global2 ? resolveGlobalConfigPath() : join33(process.cwd(), "config", "mcporter.json");
|
|
61522
62305
|
const server = {
|
|
61523
62306
|
type: "http",
|
|
61524
62307
|
url: mcpEndpoint(cfg),
|
|
@@ -61527,7 +62310,7 @@ var MCPorterProvider = () => ({
|
|
|
61527
62310
|
installJSONServer(configPath, "mcpServers", server);
|
|
61528
62311
|
},
|
|
61529
62312
|
remove(global2) {
|
|
61530
|
-
const configPath = global2 ? resolveGlobalConfigPath() :
|
|
62313
|
+
const configPath = global2 ? resolveGlobalConfigPath() : join33(process.cwd(), "config", "mcporter.json");
|
|
61531
62314
|
removeJSONServer(configPath, "mcpServers");
|
|
61532
62315
|
}
|
|
61533
62316
|
});
|
|
@@ -61537,7 +62320,7 @@ var init_mcporter = __esm(() => {
|
|
|
61537
62320
|
});
|
|
61538
62321
|
|
|
61539
62322
|
// src/mcp/providers/opencode.ts
|
|
61540
|
-
import { join as
|
|
62323
|
+
import { join as join34 } from "node:path";
|
|
61541
62324
|
var OpenCodeProvider = () => createJSONProvider({
|
|
61542
62325
|
providerName: "OpenCode",
|
|
61543
62326
|
providerID: "opencode",
|
|
@@ -61552,23 +62335,23 @@ var OpenCodeProvider = () => createJSONProvider({
|
|
|
61552
62335
|
enabled: true,
|
|
61553
62336
|
headers
|
|
61554
62337
|
}),
|
|
61555
|
-
localConfigPath: (cwd) =>
|
|
62338
|
+
localConfigPath: (cwd) => join34(cwd, "opencode.json")
|
|
61556
62339
|
});
|
|
61557
62340
|
var init_opencode = __esm(() => {
|
|
61558
62341
|
init_base();
|
|
61559
62342
|
});
|
|
61560
62343
|
|
|
61561
62344
|
// src/mcp/providers/vscode.ts
|
|
61562
|
-
import { join as
|
|
62345
|
+
import { join as join35 } from "node:path";
|
|
61563
62346
|
var VSCodeProvider = () => createJSONProvider({
|
|
61564
62347
|
providerName: "VS Code",
|
|
61565
62348
|
providerID: "vscode",
|
|
61566
62349
|
local: true,
|
|
61567
62350
|
priorityValue: 6,
|
|
61568
|
-
paths: [
|
|
61569
|
-
globalPath:
|
|
62351
|
+
paths: [join35(appSupportDir(), "Code")],
|
|
62352
|
+
globalPath: join35(appSupportDir(), "Code", "User", "mcp.json"),
|
|
61570
62353
|
topKey: "servers",
|
|
61571
|
-
localConfigPath: (cwd) =>
|
|
62354
|
+
localConfigPath: (cwd) => join35(cwd, ".vscode", "mcp.json")
|
|
61572
62355
|
});
|
|
61573
62356
|
var init_vscode = __esm(() => {
|
|
61574
62357
|
init_detect();
|
|
@@ -61577,14 +62360,14 @@ var init_vscode = __esm(() => {
|
|
|
61577
62360
|
|
|
61578
62361
|
// src/mcp/providers/windsurf.ts
|
|
61579
62362
|
import { homedir as homedir10 } from "node:os";
|
|
61580
|
-
import { join as
|
|
62363
|
+
import { join as join36 } from "node:path";
|
|
61581
62364
|
var WindsurfProvider = () => createJSONProvider({
|
|
61582
62365
|
providerName: "Windsurf",
|
|
61583
62366
|
providerID: "windsurf",
|
|
61584
62367
|
local: false,
|
|
61585
62368
|
priorityValue: 9,
|
|
61586
|
-
paths: [
|
|
61587
|
-
globalPath:
|
|
62369
|
+
paths: [join36(homedir10(), ".codeium", "windsurf")],
|
|
62370
|
+
globalPath: join36(homedir10(), ".codeium", "windsurf", "mcp_config.json"),
|
|
61588
62371
|
topKey: "mcpServers"
|
|
61589
62372
|
});
|
|
61590
62373
|
var init_windsurf = __esm(() => {
|
|
@@ -61592,27 +62375,27 @@ var init_windsurf = __esm(() => {
|
|
|
61592
62375
|
});
|
|
61593
62376
|
|
|
61594
62377
|
// src/mcp/providers/zed.ts
|
|
61595
|
-
import { rmSync as
|
|
62378
|
+
import { rmSync as rmSync6 } from "node:fs";
|
|
61596
62379
|
import { homedir as homedir11, platform as platform3 } from "node:os";
|
|
61597
|
-
import { join as
|
|
62380
|
+
import { join as join37 } from "node:path";
|
|
61598
62381
|
function zedConfigDir() {
|
|
61599
62382
|
const os = platform3();
|
|
61600
62383
|
if (os === "win32")
|
|
61601
|
-
return
|
|
62384
|
+
return join37(appSupportDir(), "Zed");
|
|
61602
62385
|
if (os === "darwin")
|
|
61603
|
-
return
|
|
61604
|
-
return
|
|
62386
|
+
return join37(homedir11(), ".config", "zed");
|
|
62387
|
+
return join37(appSupportDir(), "zed");
|
|
61605
62388
|
}
|
|
61606
62389
|
function zedDataDir() {
|
|
61607
62390
|
const os = platform3();
|
|
61608
62391
|
if (os === "darwin")
|
|
61609
|
-
return
|
|
62392
|
+
return join37(appSupportDir(), "Zed");
|
|
61610
62393
|
if (os === "win32")
|
|
61611
|
-
return
|
|
61612
|
-
return
|
|
62394
|
+
return join37(process.env.LOCALAPPDATA ?? "", "Zed");
|
|
62395
|
+
return join37(process.env.XDG_DATA_HOME ?? join37(homedir11(), ".local", "share"), "zed");
|
|
61613
62396
|
}
|
|
61614
62397
|
function legacyDarwinSettingsPath() {
|
|
61615
|
-
return platform3() === "darwin" ?
|
|
62398
|
+
return platform3() === "darwin" ? join37(appSupportDir(), "Zed", "settings.json") : null;
|
|
61616
62399
|
}
|
|
61617
62400
|
function removeLegacyDosuEntry(path) {
|
|
61618
62401
|
let cfg;
|
|
@@ -61627,7 +62410,7 @@ function removeLegacyDosuEntry(path) {
|
|
|
61627
62410
|
delete servers.dosu;
|
|
61628
62411
|
const nothingElse = Object.keys(cfg).length === 1 && Object.keys(servers).length === 0;
|
|
61629
62412
|
if (nothingElse)
|
|
61630
|
-
|
|
62413
|
+
rmSync6(path, { force: true });
|
|
61631
62414
|
else
|
|
61632
62415
|
saveJSONConfig(path, cfg);
|
|
61633
62416
|
}
|
|
@@ -61638,10 +62421,10 @@ var ZedProvider = (legacyPath = legacyDarwinSettingsPath()) => {
|
|
|
61638
62421
|
local: true,
|
|
61639
62422
|
priorityValue: 10,
|
|
61640
62423
|
paths: [zedConfigDir(), zedDataDir()],
|
|
61641
|
-
globalPath:
|
|
62424
|
+
globalPath: join37(zedConfigDir(), "settings.json"),
|
|
61642
62425
|
topKey: "context_servers",
|
|
61643
62426
|
buildServer: ({ url, headers }) => ({ url, headers }),
|
|
61644
|
-
localConfigPath: (cwd) =>
|
|
62427
|
+
localConfigPath: (cwd) => join37(cwd, ".zed", "settings.json")
|
|
61645
62428
|
});
|
|
61646
62429
|
if (!legacyPath)
|
|
61647
62430
|
return provider;
|
|
@@ -61747,7 +62530,7 @@ var init_refresh = __esm(() => {
|
|
|
61747
62530
|
|
|
61748
62531
|
// src/version/update-check.ts
|
|
61749
62532
|
import { existsSync as existsSync23, mkdirSync as mkdirSync13, readFileSync as readFileSync22, writeFileSync as writeFileSync14 } from "node:fs";
|
|
61750
|
-
import { join as
|
|
62533
|
+
import { join as join38 } from "node:path";
|
|
61751
62534
|
function isValidVersion(value) {
|
|
61752
62535
|
return typeof value === "string" && SEMVER_PATTERN.test(value);
|
|
61753
62536
|
}
|
|
@@ -61768,12 +62551,12 @@ function isNewerVersion(latest, current) {
|
|
|
61768
62551
|
}
|
|
61769
62552
|
return false;
|
|
61770
62553
|
}
|
|
61771
|
-
function
|
|
61772
|
-
return
|
|
62554
|
+
function getCachePath2() {
|
|
62555
|
+
return join38(getConfigDir(), CACHE_FILENAME3);
|
|
61773
62556
|
}
|
|
61774
62557
|
function readCache() {
|
|
61775
62558
|
try {
|
|
61776
|
-
const path =
|
|
62559
|
+
const path = getCachePath2();
|
|
61777
62560
|
if (!existsSync23(path))
|
|
61778
62561
|
return null;
|
|
61779
62562
|
const data = JSON.parse(readFileSync22(path, "utf-8"));
|
|
@@ -61791,12 +62574,12 @@ function writeCache(cache) {
|
|
|
61791
62574
|
if (!existsSync23(dir)) {
|
|
61792
62575
|
mkdirSync13(dir, { recursive: true, mode: 448 });
|
|
61793
62576
|
}
|
|
61794
|
-
writeFileSync14(
|
|
62577
|
+
writeFileSync14(getCachePath2(), JSON.stringify(cache), { mode: 384 });
|
|
61795
62578
|
} catch {}
|
|
61796
62579
|
}
|
|
61797
62580
|
async function fetchLatestVersion() {
|
|
61798
62581
|
const controller = new AbortController;
|
|
61799
|
-
const timeout = setTimeout(() => controller.abort(),
|
|
62582
|
+
const timeout = setTimeout(() => controller.abort(), FETCH_TIMEOUT_MS2);
|
|
61800
62583
|
try {
|
|
61801
62584
|
const resp = await fetch(REGISTRY_URL, { signal: controller.signal });
|
|
61802
62585
|
if (!resp.ok)
|
|
@@ -61819,29 +62602,29 @@ function buildUpdateHint(channel, npx = false) {
|
|
|
61819
62602
|
function styleHint(hint) {
|
|
61820
62603
|
const match = hint.match(/^(.*)("[^"]+")(.*)$/);
|
|
61821
62604
|
if (!match)
|
|
61822
|
-
return
|
|
62605
|
+
return import_picocolors31.default.dim(hint);
|
|
61823
62606
|
const [, before, command, after] = match;
|
|
61824
|
-
return [before &&
|
|
62607
|
+
return [before && import_picocolors31.default.dim(before), import_picocolors31.default.cyan(command), after && import_picocolors31.default.dim(after)].filter(Boolean).join("");
|
|
61825
62608
|
}
|
|
61826
62609
|
function buildUpdateNotice(current, latest, channel, interactive, npx = false, width = process.stderr.columns ?? 80) {
|
|
61827
62610
|
const hint = buildUpdateHint(channel, npx);
|
|
61828
62611
|
if (interactive) {
|
|
61829
62612
|
const content = [
|
|
61830
|
-
`Update available: ${
|
|
62613
|
+
`Update available: ${import_picocolors31.default.dim(current)} ${import_picocolors31.default.dim("→")} ${import_picocolors31.default.bold(brand(latest))}`,
|
|
61831
62614
|
styleHint(hint)
|
|
61832
62615
|
];
|
|
61833
62616
|
const innerWidth = Math.max(...content.map(visibleWidth2)) + BOX_PADDING * 2;
|
|
61834
62617
|
const framed = (line) => {
|
|
61835
62618
|
const pad = innerWidth - visibleWidth2(line);
|
|
61836
62619
|
const left = Math.floor(pad / 2);
|
|
61837
|
-
return `${
|
|
62620
|
+
return `${import_picocolors31.default.yellow("│")}${" ".repeat(left)}${line}${" ".repeat(pad - left)}${import_picocolors31.default.yellow("│")}`;
|
|
61838
62621
|
};
|
|
61839
62622
|
const box = [
|
|
61840
|
-
|
|
62623
|
+
import_picocolors31.default.yellow(`╭${"─".repeat(innerWidth)}╮`),
|
|
61841
62624
|
framed(""),
|
|
61842
62625
|
...content.map(framed),
|
|
61843
62626
|
framed(""),
|
|
61844
|
-
|
|
62627
|
+
import_picocolors31.default.yellow(`╰${"─".repeat(innerWidth)}╯`)
|
|
61845
62628
|
];
|
|
61846
62629
|
return `
|
|
61847
62630
|
${centerBlock(box, width).join(`
|
|
@@ -61859,17 +62642,17 @@ function getAvailableUpdate() {
|
|
|
61859
62642
|
const cache = readCache();
|
|
61860
62643
|
return cache && isNewerVersion(cache.latestVersion, VERSION) ? cache.latestVersion : null;
|
|
61861
62644
|
}
|
|
61862
|
-
function
|
|
62645
|
+
function displayNotice(current, latest) {
|
|
61863
62646
|
console.error(buildUpdateNotice(current, latest, INSTALL_CHANNEL, process.stderr.isTTY === true, isNpxInvocation()));
|
|
61864
62647
|
}
|
|
61865
62648
|
async function checkForUpdates(options = {}) {
|
|
61866
62649
|
const notify = options.notify ?? true;
|
|
61867
62650
|
try {
|
|
61868
62651
|
const cache = readCache();
|
|
61869
|
-
const isStale = !cache || Date.now() - cache.lastCheck >
|
|
62652
|
+
const isStale = !cache || Date.now() - cache.lastCheck > CHECK_INTERVAL_MS2;
|
|
61870
62653
|
if (!isStale) {
|
|
61871
62654
|
if (notify && isNewerVersion(cache.latestVersion, VERSION)) {
|
|
61872
|
-
|
|
62655
|
+
displayNotice(VERSION, cache.latestVersion);
|
|
61873
62656
|
}
|
|
61874
62657
|
return;
|
|
61875
62658
|
}
|
|
@@ -61883,26 +62666,26 @@ async function checkForUpdates(options = {}) {
|
|
|
61883
62666
|
logger.debug("update-check", `Cached latest version: ${latest}`);
|
|
61884
62667
|
}
|
|
61885
62668
|
if (notify && isNewerVersion(latestKnownVersion, VERSION)) {
|
|
61886
|
-
|
|
62669
|
+
displayNotice(VERSION, latestKnownVersion);
|
|
61887
62670
|
}
|
|
61888
62671
|
} catch (err) {
|
|
61889
62672
|
logger.error("update-check", `Update check failed: ${err}`);
|
|
61890
62673
|
}
|
|
61891
62674
|
}
|
|
61892
|
-
var
|
|
62675
|
+
var import_picocolors31, CACHE_FILENAME3 = "update-check.json", CHECK_INTERVAL_MS2, FETCH_TIMEOUT_MS2 = 1000, REGISTRY_URL = "https://registry.npmjs.org/-/package/@dosu/cli/dist-tags", SEMVER_PATTERN, BOX_PADDING = 3;
|
|
61893
62676
|
var init_update_check = __esm(() => {
|
|
61894
62677
|
init_config();
|
|
61895
62678
|
init_logger();
|
|
61896
62679
|
init_styles();
|
|
61897
62680
|
init_layout();
|
|
61898
|
-
|
|
61899
|
-
|
|
62681
|
+
import_picocolors31 = __toESM(require_picocolors(), 1);
|
|
62682
|
+
CHECK_INTERVAL_MS2 = 6 * 60 * 60 * 1000;
|
|
61900
62683
|
SEMVER_PATTERN = /^(?:0|[1-9]\d*)\.(?:0|[1-9]\d*)\.(?:0|[1-9]\d*)(?:-[0-9A-Za-z-]+(?:\.[0-9A-Za-z-]+)*)?(?:\+[0-9A-Za-z-]+(?:\.[0-9A-Za-z-]+)*)?$/;
|
|
61901
62684
|
});
|
|
61902
62685
|
|
|
61903
62686
|
// src/version/mcp-refresh-check.ts
|
|
61904
62687
|
import { existsSync as existsSync24, mkdirSync as mkdirSync14, readFileSync as readFileSync23, writeFileSync as writeFileSync15 } from "node:fs";
|
|
61905
|
-
import { join as
|
|
62688
|
+
import { join as join39 } from "node:path";
|
|
61906
62689
|
function needsMcpRefresh(previous, current) {
|
|
61907
62690
|
if (previous === null)
|
|
61908
62691
|
return true;
|
|
@@ -61911,12 +62694,12 @@ function needsMcpRefresh(previous, current) {
|
|
|
61911
62694
|
const [older, newer] = isNewerVersion(current, previous) ? [previous, current] : [current, previous];
|
|
61912
62695
|
return MCP_FORMAT_CHANGES.some((change) => isNewerVersion(change, older) && !isNewerVersion(change, newer));
|
|
61913
62696
|
}
|
|
61914
|
-
function
|
|
61915
|
-
return
|
|
62697
|
+
function getCachePath3() {
|
|
62698
|
+
return join39(getConfigDir(), CACHE_FILENAME4);
|
|
61916
62699
|
}
|
|
61917
62700
|
function readMcpRefreshCache() {
|
|
61918
62701
|
try {
|
|
61919
|
-
const path =
|
|
62702
|
+
const path = getCachePath3();
|
|
61920
62703
|
if (!existsSync24(path))
|
|
61921
62704
|
return null;
|
|
61922
62705
|
const data = JSON.parse(readFileSync23(path, "utf-8"));
|
|
@@ -61933,7 +62716,7 @@ function writeMcpRefreshCache(cache) {
|
|
|
61933
62716
|
if (!existsSync24(dir)) {
|
|
61934
62717
|
mkdirSync14(dir, { recursive: true, mode: 448 });
|
|
61935
62718
|
}
|
|
61936
|
-
writeFileSync15(
|
|
62719
|
+
writeFileSync15(getCachePath3(), JSON.stringify(cache), { mode: 384 });
|
|
61937
62720
|
} catch {}
|
|
61938
62721
|
}
|
|
61939
62722
|
function canRefreshMcp(cfg) {
|
|
@@ -61942,10 +62725,10 @@ function canRefreshMcp(cfg) {
|
|
|
61942
62725
|
return false;
|
|
61943
62726
|
return cfg.mode === MODE_OSS || Boolean(target.deployment_id);
|
|
61944
62727
|
}
|
|
61945
|
-
function
|
|
62728
|
+
function displayNotice2(names) {
|
|
61946
62729
|
console.error(`
|
|
61947
|
-
${
|
|
61948
|
-
` + `${
|
|
62730
|
+
${import_picocolors32.default.green(`✓ Dosu ${VERSION}: refreshed MCP config for ${names.join(", ")}`)}
|
|
62731
|
+
` + `${import_picocolors32.default.dim(` Run ${import_picocolors32.default.cyan('"dosu setup"')} to also update hooks and rules, then restart your AI agents.`)}
|
|
61949
62732
|
`);
|
|
61950
62733
|
}
|
|
61951
62734
|
function checkForMcpRefresh(options = {}) {
|
|
@@ -61967,31 +62750,63 @@ function checkForMcpRefresh(options = {}) {
|
|
|
61967
62750
|
writeMcpRefreshCache({ version: VERSION });
|
|
61968
62751
|
logger.info("mcp-refresh", `Version ${VERSION}: refreshed ${result.updated.length}, failed ${result.failed.length}`);
|
|
61969
62752
|
if (notify && result.updated.length > 0) {
|
|
61970
|
-
|
|
62753
|
+
displayNotice2(result.updated.map((provider) => provider.name()));
|
|
61971
62754
|
}
|
|
61972
62755
|
} catch (err) {
|
|
61973
62756
|
logger.error("mcp-refresh", `MCP refresh check failed: ${err}`);
|
|
61974
62757
|
}
|
|
61975
62758
|
}
|
|
61976
|
-
var
|
|
62759
|
+
var import_picocolors32, CACHE_FILENAME4 = "mcp-refresh.json", MCP_FORMAT_CHANGES;
|
|
61977
62760
|
var init_mcp_refresh_check = __esm(() => {
|
|
61978
62761
|
init_config();
|
|
61979
62762
|
init_logger();
|
|
61980
62763
|
init_refresh();
|
|
61981
62764
|
init_update_check();
|
|
61982
|
-
|
|
62765
|
+
import_picocolors32 = __toESM(require_picocolors(), 1);
|
|
61983
62766
|
MCP_FORMAT_CHANGES = ["0.53.0"];
|
|
61984
62767
|
});
|
|
61985
62768
|
|
|
62769
|
+
// src/version/skill-update-check.ts
|
|
62770
|
+
function displayNotice3() {
|
|
62771
|
+
console.error(`
|
|
62772
|
+
${import_picocolors33.default.green(`✓ Dosu ${VERSION}: refreshed the bundled agent skills`)}
|
|
62773
|
+
` + `${import_picocolors33.default.dim(" Restart your AI agents to pick up the new skill content.")}
|
|
62774
|
+
`);
|
|
62775
|
+
}
|
|
62776
|
+
function checkForSkillUpdates(options = {}) {
|
|
62777
|
+
const notify = options.notify ?? true;
|
|
62778
|
+
try {
|
|
62779
|
+
const state = readSkillInstallState();
|
|
62780
|
+
if (!state || state.version === VERSION)
|
|
62781
|
+
return;
|
|
62782
|
+
const result = installBundledSkills(state.agents);
|
|
62783
|
+
if (!result.success) {
|
|
62784
|
+
logger.error("skill-update-check", `Skill refresh to ${VERSION} failed; will retry`);
|
|
62785
|
+
return;
|
|
62786
|
+
}
|
|
62787
|
+
logger.info("skill-update-check", `Refreshed skills from ${state.version} to ${VERSION}`);
|
|
62788
|
+
if (notify && result.version)
|
|
62789
|
+
displayNotice3();
|
|
62790
|
+
} catch (err) {
|
|
62791
|
+
logger.error("skill-update-check", `Skill update check failed: ${err}`);
|
|
62792
|
+
}
|
|
62793
|
+
}
|
|
62794
|
+
var import_picocolors33;
|
|
62795
|
+
var init_skill_update_check = __esm(() => {
|
|
62796
|
+
init_skill();
|
|
62797
|
+
init_logger();
|
|
62798
|
+
import_picocolors33 = __toESM(require_picocolors(), 1);
|
|
62799
|
+
});
|
|
62800
|
+
|
|
61986
62801
|
// src/rules/installer.ts
|
|
61987
62802
|
import { existsSync as existsSync25, mkdirSync as mkdirSync15, readFileSync as readFileSync24, unlinkSync as unlinkSync5, writeFileSync as writeFileSync16 } from "node:fs";
|
|
61988
62803
|
import { homedir as homedir12 } from "node:os";
|
|
61989
|
-
import { dirname as
|
|
62804
|
+
import { dirname as dirname12, join as join40 } from "node:path";
|
|
61990
62805
|
function claudeConfigDir4() {
|
|
61991
|
-
return process.env.CLAUDE_CONFIG_DIR ||
|
|
62806
|
+
return process.env.CLAUDE_CONFIG_DIR || join40(homedir12(), ".claude");
|
|
61992
62807
|
}
|
|
61993
62808
|
function codexHome4() {
|
|
61994
|
-
return process.env.CODEX_HOME ||
|
|
62809
|
+
return process.env.CODEX_HOME || join40(homedir12(), ".codex");
|
|
61995
62810
|
}
|
|
61996
62811
|
function isRuleAgent(agent) {
|
|
61997
62812
|
return Object.hasOwn(RULE_TARGETS, agent);
|
|
@@ -62017,7 +62832,7 @@ async function fetchDosuRule(fetchImpl = globalThis.fetch) {
|
|
|
62017
62832
|
return normalizeRule(FALLBACK_DOSU_RULE);
|
|
62018
62833
|
}
|
|
62019
62834
|
function ensureParent(path) {
|
|
62020
|
-
mkdirSync15(
|
|
62835
|
+
mkdirSync15(dirname12(path), { recursive: true });
|
|
62021
62836
|
}
|
|
62022
62837
|
function writeIfChanged(path, content) {
|
|
62023
62838
|
if (!existsSync25(path)) {
|
|
@@ -62133,39 +62948,39 @@ var init_installer = __esm(() => {
|
|
|
62133
62948
|
RULE_TARGETS = {
|
|
62134
62949
|
claude: {
|
|
62135
62950
|
kind: "file",
|
|
62136
|
-
path: () =>
|
|
62951
|
+
path: () => join40(claudeConfigDir4(), "rules", "dosu.md")
|
|
62137
62952
|
},
|
|
62138
62953
|
cursor: {
|
|
62139
62954
|
kind: "file",
|
|
62140
|
-
path: () =>
|
|
62955
|
+
path: () => join40(homedir12(), ".cursor", "rules", "dosu.mdc"),
|
|
62141
62956
|
cursorFrontmatter: true
|
|
62142
62957
|
},
|
|
62143
62958
|
codex: {
|
|
62144
62959
|
kind: "section",
|
|
62145
|
-
path: () =>
|
|
62960
|
+
path: () => join40(codexHome4(), "AGENTS.md")
|
|
62146
62961
|
},
|
|
62147
62962
|
opencode: {
|
|
62148
62963
|
kind: "section",
|
|
62149
|
-
path: () =>
|
|
62964
|
+
path: () => join40(homedir12(), ".config", "opencode", "AGENTS.md")
|
|
62150
62965
|
},
|
|
62151
62966
|
gemini: {
|
|
62152
62967
|
kind: "section",
|
|
62153
|
-
path: () =>
|
|
62968
|
+
path: () => join40(homedir12(), ".gemini", "GEMINI.md")
|
|
62154
62969
|
},
|
|
62155
62970
|
antigravity: {
|
|
62156
62971
|
kind: "section",
|
|
62157
|
-
path: () =>
|
|
62972
|
+
path: () => join40(homedir12(), ".gemini", "GEMINI.md")
|
|
62158
62973
|
}
|
|
62159
62974
|
};
|
|
62160
62975
|
});
|
|
62161
62976
|
|
|
62162
62977
|
// src/setup/agents-md-step.ts
|
|
62163
|
-
import { execSync as
|
|
62978
|
+
import { execSync as execSync2 } from "node:child_process";
|
|
62164
62979
|
import { existsSync as existsSync26, readFileSync as readFileSync25, writeFileSync as writeFileSync17 } from "node:fs";
|
|
62165
|
-
import { join as
|
|
62980
|
+
import { join as join41 } from "node:path";
|
|
62166
62981
|
function inGitWorkTree(cwd = process.cwd()) {
|
|
62167
62982
|
try {
|
|
62168
|
-
const stdout =
|
|
62983
|
+
const stdout = execSync2("git rev-parse --is-inside-work-tree", {
|
|
62169
62984
|
cwd,
|
|
62170
62985
|
stdio: ["ignore", "pipe", "ignore"]
|
|
62171
62986
|
});
|
|
@@ -62176,7 +62991,7 @@ function inGitWorkTree(cwd = process.cwd()) {
|
|
|
62176
62991
|
}
|
|
62177
62992
|
function dosuAgentsSectionState(cwd = process.cwd()) {
|
|
62178
62993
|
try {
|
|
62179
|
-
const path =
|
|
62994
|
+
const path = join41(cwd, "AGENTS.md");
|
|
62180
62995
|
if (!existsSync26(path))
|
|
62181
62996
|
return "missing";
|
|
62182
62997
|
const content = readFileSync25(path, "utf-8");
|
|
@@ -62214,7 +63029,7 @@ function findSection2(content) {
|
|
|
62214
63029
|
return { start, end };
|
|
62215
63030
|
}
|
|
62216
63031
|
function upsertDosuAgentsSection(cwd = process.cwd(), content = FALLBACK_DOSU_RULE) {
|
|
62217
|
-
const path =
|
|
63032
|
+
const path = join41(cwd, "AGENTS.md");
|
|
62218
63033
|
if (!existsSync26(path)) {
|
|
62219
63034
|
const section = buildDosuAgentsSection(content);
|
|
62220
63035
|
writeFileSync17(path, `${section}
|
|
@@ -62291,9 +63106,9 @@ var MCP_PROVIDER_SLUG2 = "dosu_mcp";
|
|
|
62291
63106
|
// src/sessions/session-title.ts
|
|
62292
63107
|
import { existsSync as existsSync27, mkdirSync as mkdirSync16, readFileSync as readFileSync26, renameSync as renameSync6, statSync as statSync9, writeFileSync as writeFileSync18 } from "node:fs";
|
|
62293
63108
|
import { homedir as homedir13 } from "node:os";
|
|
62294
|
-
import { join as
|
|
63109
|
+
import { join as join42 } from "node:path";
|
|
62295
63110
|
function cachePath2(configDir) {
|
|
62296
|
-
return
|
|
63111
|
+
return join42(configDir, CACHE_FILENAME5);
|
|
62297
63112
|
}
|
|
62298
63113
|
function loadCacheFile2(configDir) {
|
|
62299
63114
|
try {
|
|
@@ -62350,10 +63165,10 @@ function reconstructSession(harness, id, slug, home = homedir13(), exists = exis
|
|
|
62350
63165
|
return null;
|
|
62351
63166
|
const candidates = [];
|
|
62352
63167
|
if (harness === "claude") {
|
|
62353
|
-
candidates.push(
|
|
63168
|
+
candidates.push(join42(home, ".claude", "projects", slug, `${id}.jsonl`));
|
|
62354
63169
|
} else if (harness === "cursor") {
|
|
62355
|
-
const project =
|
|
62356
|
-
candidates.push(
|
|
63170
|
+
const project = join42(home, ".cursor", "projects", slug);
|
|
63171
|
+
candidates.push(join42(project, "agent-transcripts", id, `${id}.jsonl`), join42(project, "agent-transcripts", `${id}.jsonl`));
|
|
62357
63172
|
} else {
|
|
62358
63173
|
return null;
|
|
62359
63174
|
}
|
|
@@ -62416,7 +63231,7 @@ function createSessionTitleResolver(configDir = getConfigDir(), deps = {}) {
|
|
|
62416
63231
|
}
|
|
62417
63232
|
};
|
|
62418
63233
|
}
|
|
62419
|
-
var
|
|
63234
|
+
var CACHE_FILENAME5 = "session-titles.json", CACHE_SCHEMA_VERSION2 = 3, HEAD_LINES2 = 50, SESSION_NAME_MAX = 80;
|
|
62420
63235
|
var init_session_title = __esm(() => {
|
|
62421
63236
|
init_config();
|
|
62422
63237
|
init_read();
|
|
@@ -63928,9 +64743,9 @@ async function runInstallSkill(providers) {
|
|
|
63928
64743
|
const agentLabel = providers.length === 1 ? "agent" : "agents";
|
|
63929
64744
|
spinner.start(`Installing skill for ${providers.length} ${agentLabel}`);
|
|
63930
64745
|
try {
|
|
63931
|
-
const result = await installSkill(providers.map((provider) => provider.id())
|
|
64746
|
+
const result = await installSkill(providers.map((provider) => provider.id()));
|
|
63932
64747
|
if (result.success) {
|
|
63933
|
-
logger.info("setup", `Skill installed${result.
|
|
64748
|
+
logger.info("setup", `Skill installed${result.version ? ` v${result.version}` : ""}`);
|
|
63934
64749
|
const items = providers.flatMap((provider) => {
|
|
63935
64750
|
const target = skillInstallTargetForProvider(provider.id());
|
|
63936
64751
|
if (!target)
|
|
@@ -66077,7 +66892,7 @@ async function runAgentSetup(opts) {
|
|
|
66077
66892
|
}
|
|
66078
66893
|
if (skillAgentIDsForProviders([provider.id()]).length > 0) {
|
|
66079
66894
|
try {
|
|
66080
|
-
const skill = await installSkill([provider.id()]
|
|
66895
|
+
const skill = await installSkill([provider.id()]);
|
|
66081
66896
|
if (!skill.success) {
|
|
66082
66897
|
throw new Error("the skills installer failed");
|
|
66083
66898
|
}
|
|
@@ -66085,7 +66900,8 @@ async function runAgentSetup(opts) {
|
|
|
66085
66900
|
step: "skill_install",
|
|
66086
66901
|
tool: provider.id(),
|
|
66087
66902
|
tool_name: provider.name(),
|
|
66088
|
-
source: "dosu
|
|
66903
|
+
source: "@dosu/cli",
|
|
66904
|
+
version: skill.version
|
|
66089
66905
|
});
|
|
66090
66906
|
} catch (err) {
|
|
66091
66907
|
emitError({
|
|
@@ -66364,7 +67180,10 @@ function shouldRunBackgroundChecks(actionName) {
|
|
|
66364
67180
|
function shouldRunMcpRefreshCheck(actionCommand) {
|
|
66365
67181
|
if (actionCommand.name() === "setup")
|
|
66366
67182
|
return false;
|
|
66367
|
-
|
|
67183
|
+
const parent = actionCommand.parent?.name();
|
|
67184
|
+
if (actionCommand.name() === "refresh" && parent === "mcp")
|
|
67185
|
+
return false;
|
|
67186
|
+
return !(actionCommand.name() === "sync" && parent === "knowledge");
|
|
66368
67187
|
}
|
|
66369
67188
|
function commandTelemetryName(actionCommand) {
|
|
66370
67189
|
const segments = [];
|
|
@@ -66464,7 +67283,7 @@ function createProgram(options = {}) {
|
|
|
66464
67283
|
if (!process.env.CI) {
|
|
66465
67284
|
await checkForUpdates({ notify: !launchesTUI });
|
|
66466
67285
|
}
|
|
66467
|
-
checkForSkillUpdates();
|
|
67286
|
+
checkForSkillUpdates({ notify: !launchesTUI });
|
|
66468
67287
|
checkForReadyTasks();
|
|
66469
67288
|
if (shouldRunMcpRefreshCheck(actionCommand)) {
|
|
66470
67289
|
checkForMcpRefresh({ notify: !launchesTUI });
|
|
@@ -66942,4 +67761,4 @@ main().catch((err) => {
|
|
|
66942
67761
|
process.exit(1);
|
|
66943
67762
|
});
|
|
66944
67763
|
|
|
66945
|
-
//# debugId=
|
|
67764
|
+
//# debugId=ecb91fd5-693a-ffc0-6475-6e2164756e21
|