SuperAPI AI Directory

wiki-pages

Coding & development

View repository

Updated 10-15 21:11

About this skill

Wiki pages

This Skill reads the Wiki and, after user confirmation, creates or updates pages. It does not provide deletion, moving, or renaming of pages; when needed, ask the user to perform the operation in the web interface.

Project selection

  • If the user has provided a project name (for example "Contoso project"), use it directly and do not call the project list API.

  • When the user only wants to "search the Wiki across the entire organization", for rule 4 use the URL without a project, and no project selection is needed.

  • In other cases, if it is not provided, ask the user to provide it once.

  • If it is still not provided, list the projects for the user to choose:

    curl -sS -u ":$AZURE_DEVOPS_PAT" \
      "https://dev.azure.com/$AZURE_DEVOPS_ORG/_apis/projects?%24top=500&api-version=7.1"
    
  • Do not continue before the user provides or selects a project.

Wiki selection

  • If the user has provided a Wiki name, use it directly;{wikiIdentifier} it can be the Wiki's id or name(the name must be URL-encoded).
  • If it is not provided, list the project's wikis using rule 1: if there is only one, use it directly; if there are multiple, ask the user to choose.
  • If what the user gives is the page URL https://dev.azure.com/{org}/{project}/_wiki/wikis/{wikiName}/{pageId}/{slug} , extract the project, Wiki name, and pageId, and read by ID according to rule 3.

Connection and authentication

Always use curl to call the Azure DevOps REST API directly; each command carries its own authentication parameters.

  • Organization: read the environment variable AZURE_DEVOPS_ORG(organization name, for example contoso). If it is not set, ask the user once; if what the user gives is a URL, extract the organization name from https://dev.azure.com/{org} or https://{org}.visualstudio.com .
  • Host: other than dev.azure.com, the host for the Wiki search API is almsearch.dev.azure.com。
  • Token: the PAT is sent with Basic authentication:-u ":$AZURE_DEVOPS_PAT"; if only AZURE_DEVOPS_EXT_PATis set (the variable used by the Azure CLI azure-devops extension), use that instead. When using a Microsoft Entra ID token instead, replace with -H "Authorization: Bearer $AZURE_DEVOPS_TOKEN". If neither is set, ask the user to set AZURE_DEVOPS_PAT in their own terminal and retry, and stop. Read the token only from environment variables: do not ask the user to paste the token into the conversation, and do not print it or write it to a file.
  • PAT permission scopes: required for reading: Wiki (Read) (already includes Wiki search); required for writing: Wiki (Read & write) (create and update pages).
  • Encoding: the project and Wiki names in the path, the page path in the query string, and comment must be URL-encoded (write spaces as %20, see "Page path" for the rules); in the query string, write $ as %24(for example %24top), to avoid shell expansion.
  • Errors: HTTP 401, 403, 203, or a response that is an HTML login page means the token is invalid, expired, or has insufficient permissions; report it and stop. HTTP 404 means the organization, project, Wiki, or page path is incorrect (when the page does not exist, typeKey is WikiPageNotFoundException). A code wiki specifying a nonexistent branch returns HTTP 500 (TF401175)。
  • Windows PowerShell: call curl.exe(instead of curl alias), write the environment variable as $env:AZURE_DEVOPS_PAT; PowerShell does not support <<'EOF', first write the JSON body to a temporary file, then use --data-binary "@body.json" to send it.

Page path

  • Page path(the API's path) starts with / , consists of the page title, preserves spaces, for example /Release Notes/v1.0; the root directory is /. code wiki page paths are relative to mappedPath。
  • Title restrictions: cannot contain /、\、#, cannot start or end with . ; the full path including the repository URL is limited to 235 characters, and a single page is limited to 18 MB.
  • Put into the query string: URL-encode the entire segment (space %20、& %26、? %3F、% %25、+ %2B, Chinese encoded in UTF-8;/ may be preserved or written as %2F). You can use jq -rn --arg p "/Release Notes/v1.0" '$p|@uri' to generate it.
  • gitItemPath is the page's file path in the Wiki repository: spaces in the title become -, the original - becomes %2D,:、*、?、|、"、<、> is also represented as %XX , and finally append .md; code wiki adds the mappedPath prefix.
  • Restore the page path from gitItemPath Restore the page path: remove the mappedPath prefix and .md, replace - with spaces, and finally URL-decode (the order cannot be reversed, otherwise %2D will be mistakenly replaced with spaces).

Rules

1. List Wikis

curl -sS -u ":$AZURE_DEVOPS_PAT" \
  "https://dev.azure.com/$AZURE_DEVOPS_ORG/{project}/_apis/wiki/wikis?api-version=7.1"

Each entry has id、name、type(projectWiki is a project Wiki;codeWiki is a Wiki published from a repository folder),repositoryId、mappedPath(the folder corresponding to the code wiki),versions[].version(project wiki has a fixed single branch, for example wikiMaster; code wiki is the published branch) and remoteUrl. If there are no Wikis at all, state this clearly and stop.

Example: "What Wikis does the Contoso project have?"

2. Browse the page tree

curl -sS -u ":$AZURE_DEVOPS_PAT" \
  "https://dev.azure.com/$AZURE_DEVOPS_ORG/{project}/_apis/wiki/wikis/{wikiIdentifier}/pages?path=/&recursionLevel=oneLevel&api-version=7.1"
  • recursionLevel:oneLevel retrieves only direct child pages,full retrieves all. When there are many pages, first use oneLevel, then according to the user's needs replace path with child pages to expand level by level.
  • subPages[] Each entry has path、order(ordering within the same level),isParentPage(has child pages) and gitItemPath。
  • code wiki: when versionDescriptor is omitted, read the default published version.versions When there are multiple branches, add &versionDescriptor.version={branch}&versionDescriptor.versionType=branch to specify;{branch} only uses values from versions[].version (other branches may also return 200, but that is not the published content). project wiki does not need this parameter.

Example: "List the page structure of Contoso.wiki"

3. Read pages

curl -sS -u ":$AZURE_DEVOPS_PAT" -D - \
  "https://dev.azure.com/$AZURE_DEVOPS_ORG/{project}/_apis/wiki/wikis/{wikiIdentifier}/pages?path={pagePath}&includeContent=true&api-version=7.1"
  • -D - first prints the response headers:ETag is the page's current version (including double quotes), to be used when updating in rule 6. When only reading, -D -。
  • can be omitted. The response has content(Markdown)、id(permanent page ID),path、gitItemPath、remoteUrl(web link).
  • When the page ID is already known, use .../wiki/wikis/{wikiIdentifier}/pages/{pageId}?includeContent=true&api-version=7.1instead, which likewise returns ETag。
  • In the content, [[_TOC_]]、:::mermaid、/.attachments/... image links are Wiki-specific syntax; preserve them as-is or explain them when presenting.

Example: "Read /Release Notes/v1.0 of Contoso.wiki"

4. Search Wikis

curl -sS -u ":$AZURE_DEVOPS_PAT" -X POST -H "Content-Type: application/json" \
  "https://almsearch.dev.azure.com/$AZURE_DEVOPS_ORG/{project}/_apis/search/wikisearchresults?api-version=7.1" \
  -d '{"searchText":"deployment checklist","$skip":0,"$top":25,"filters":{"Project":["Contoso"],"Wiki":["Contoso.wiki"]},"includeFacets":true}'
  • searchText supports keywords (default AND), uppercase AND、OR、NOT, double-quoted phrases and the trailing * wildcard, case-insensitive.
  • filters.Wiki Use the Wiki'sname(using id will return no results); omit any unwanted filters entirely. When searching the entire organization, remove /{project},filters from the URL and also omit Project. Results include both project wiki and code wiki.
  • $top must be between 1 and 1000;count is the total count; when it is greater than the number already retrieved, use $skip to get the next page.includeFacets is true ,facets.Wiki[] lists the match count for each Wiki.
  • Each entry has the form fileName、path(gitItemPath , containing .md)、wiki.name、wiki.id、wiki.mappedPath、wiki.version、project.name, and hits[]:fieldReferenceName is fileNames or content,highlights[] is a snippet with matches marked by <highlighthit> .
  • Use the "page path" to restore path to a page path, then use rule 3 to read the required page.

Example: "Which page in the Wiki documents the deployment process?"

5. Create a page (write)

  1. Confirm the page does not exist: read it using rule 3, and only continue if it returns HTTP 404 (WikiPageNotFoundException); if it already exists, use rule 6 instead.

  2. Confirm the parent page exists (for example, the parent of /Release Notes/v1.0 is /Release Notes); if it does not exist, tell the user and ask whether to create the parent page first.

  3. List the content about to be sent to the user and execute only after one confirmation: Wiki, page path, full Markdown content, change description (comment)。

  4. when creatingdo not include If-Match:

    curl -sS -u ":$AZURE_DEVOPS_PAT" -X PUT -H "Content-Type: application/json" \
      "https://dev.azure.com/$AZURE_DEVOPS_ORG/{project}/_apis/wiki/wikis/{wikiIdentifier}/pages?path={pagePath}&comment={comment}&api-version=7.1" \
      --data-binary @- <<'EOF'
    {"content": "# v1.0\n\n- 新增登入功能\n- 修正匯出錯誤"}
    EOF
    

    On success, it returns HTTP 201. When the content contains newlines and quotes, first write the Markdown to a temporary file, then use jq -Rs '{content: .}' page.md to generate the JSON body.

Example: "Add a v1.0 page under /Release Notes in Contoso.wiki"

6. Update a page (write)

  1. Read the page, note down ETag, and save the current content as a temporary file old.md(jq -j does not add an extra newline at the end):

    curl -sS -u ":$AZURE_DEVOPS_PAT" -D headers.txt -o page.json \
      "https://dev.azure.com/$AZURE_DEVOPS_ORG/{project}/_apis/wiki/wikis/{wikiIdentifier}/pages?path={pagePath}&includeContent=true&api-version=7.1"
    grep -i '^etag:' headers.txt
    jq -j '.content' page.json > old.md
    
  2. Generate new content new.mdas requested by the user: change only the sections the user requested, and keep the rest of the content and formatting as-is.

  3. Show the diff, and list the Wiki, page path, change description, and diff for the user, and execute only after one confirmation:

    git diff --no-index --unified=3 old.md new.md
    
  4. when updatingmustinclude If-Match, with the value exactly as in the ETag header (including the double quotes; the {etag} in the example is the version string inside the double quotes):

    curl -sS -u ":$AZURE_DEVOPS_PAT" -X PUT -H "Content-Type: application/json" \
      -H 'If-Match: "{etag}"' \
      "https://dev.azure.com/$AZURE_DEVOPS_ORG/{project}/_apis/wiki/wikis/{wikiIdentifier}/pages?path={pagePath}&comment={comment}&api-version=7.1" \
      --data-binary "@body.json"
    

    body.json generate with jq -Rs '{content: .}' new.md > body.json . On success, it returns HTTP 200, and the ETag in the response header is the new version.

  5. If it fails and the message indicates a version mismatch, it means the page was modified by someone else during this period: start over from step 1, show the diff again, and confirm. Do not remove If-Match or resend using the old ETag .

  6. Delete temporary files once they are no longer needed.

Writing to code wiki: creation and updates commit directly to the published branch (versions when there are multiple branches, specify with the versionDescriptor parameter from rule 2). If the branch has a policy requiring a PR, the write may be rejected: instead, modify mappedPath locally under .md , then use repos-pull-request-write to open a PR.

Example: "Update the VPN setup steps in the /Onboarding page of Contoso.wiki to the new version"

Presentation of results

Dates are displayed as YYYY/MM/DD, times are converted to the user's local time zone, and UTC is indicated when it cannot be determined.

  • Wiki list: present the name in a table (link remoteUrl), type (project Wiki/code wiki), the code wiki's repository folder (mappedPath) and publishing branch.
  • Page tree: present page titles (the last segment of the path) as an indented list, and add "(has subpages)" to pages that have subpages but are not yet expanded.
  • Page content: first list the page path and web link, then present the Markdown content; when the content is very long, summarize the key points first and ask whether to display the full text.
  • Search results: first state the total number of results, then present the page path (after restoration, clickable), Wiki name and matching snippet in a table (change the <highlighthit> markup to bold). If there are no results, state this clearly.
  • Before writing: when creating, list the full content; when updating, list the diff and a description of the changes.
  • After writing: the page path, web link, and the result of the creation or update; on failure, display the HTTP status code and the messagein the response, and do not automatically retry the write.