-
Notifications
You must be signed in to change notification settings - Fork 1
Seng/agent migration #327
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Seng/agent migration #327
Conversation
📝 WalkthroughWalkthroughAdds a new doc-agents package with a document ingestion pipeline (MDX-aware chunking, embeddings, vector upserts), a RAG DocQA agent and web UI, an AgentPulse streaming agent and API, many autogenerated CLI skill docs, API routes and middleware, SDK-backed KV refactor, centralized API client/services, CI webhook/trigger updates, and assorted config and re-exports. Changes
Sequence Diagram(s)sequenceDiagram
participant Client
participant API as API Route\n(process-docs)
participant Agent as DocProcessing\nAgent
participant Chunker as MDX Chunker\n& Embeddings
participant VectorStore as Vector\nStore
participant Logger
Client->>API: POST /api/process-docs\n{commit, changed[], removed[]}
API->>Agent: validate & run payload
Agent->>Logger: log start
alt Removed files
Agent->>VectorStore: removeVectorsByPath(path) [batched deletes]
VectorStore-->>Agent: delete confirmations
Agent->>Logger: deletion stats
end
alt Changed files
Agent->>Chunker: chunkAndEnrichDoc(base64Content)
Chunker->>Chunker: parse frontmatter & hybrid chunking
Chunker-->>Agent: enriched chunks[]
Agent->>Chunker: embedChunks(texts[])
Chunker->>OpenAI: call embeddings model
OpenAI-->>Chunker: embeddings[][]
Chunker-->>Agent: embeddings
Agent->>VectorStore: batch upsert vectors (key, embedding, metadata)
VectorStore-->>Agent: upsert result
Agent->>Logger: processed file stats
end
Agent-->>API: return SyncStats
API-->>Client: 200 JSON
sequenceDiagram
participant User
participant WebUI as Web UI\n(React)
participant API as API Route\n(doc-qa)
participant Agent as DocQA\nAgent
participant Prompt as Prompt\nService
participant Retriever as Vector\nRetriever
participant OpenAI as OpenAI\nAPI
participant VectorStore as Vector\nStore
User->>WebUI: Enter question
WebUI->>API: POST /api/doc-qa\n{message}
API->>Agent: validate & run
Agent->>Prompt: rephraseVaguePrompt(message)
Prompt->>OpenAI: generateText (rephrase)
OpenAI-->>Prompt: rephrased query
Prompt-->>Agent: return rephrase
Agent->>Prompt: getPromptType(query)
Prompt->>OpenAI: generateObject (classify)
OpenAI-->>Prompt: {type, confidence}
Prompt-->>Agent: PromptType
Agent->>Retriever: retrieveRelevantDocs(query)
Retriever->>VectorStore: vector search -> chunk hits
VectorStore-->>Retriever: chunks with scores
Retriever->>Retriever: group by path & expandPathGroup (neighboring chunks)
Retriever-->>Agent: RelevantDoc[]
Agent->>OpenAI: generateObject (RAG answer + sources)
OpenAI-->>Agent: {answer, documents[]}
Agent-->>API: return answer
API-->>WebUI: JSON response
WebUI->>User: render answer + sources
Estimated code review effort🎯 4 (Complex) | ⏱️ ~60 minutes 🚥 Pre-merge checks | ✅ 1✅ Passed checks (1 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing touches
🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 14
Note
Due to the large number of review comments, Critical severity comments were prioritized as inline comments.
🟠 Major comments (37)
doc-agents/.agents/skills/agentuity-cli-cloud-deployment-remove/SKILL.md-34-39 (1)
34-39: Fix inconsistency between required flag notation and option syntax.Line 38 marks
--project-idas "Yes" (required) in the Options table, but line 25 shows it in[options]brackets, which conventionally indicates optional parameters. Clarify whether this flag is actually required and update either the table or the usage syntax accordingly to avoid user confusion.doc-agents/.agents/skills/agentuity-cli-cloud-agent-list/SKILL.md-53-55 (1)
53-55: Expand the Output section with schema details.The output documentation only states the return type (
array) without describing the structure or contents of array elements. Users need to know what fields/properties are included in each returned object.Consider expanding this section to include:
- The schema of array elements (e.g., agent name, ID, status, etc.)
- An example JSON output showing actual structure
For consistency, check other similar skill documentation files to match their output documentation style.
doc-agents/.agents/skills/agentuity-cli-cloud-session-list/SKILL.md-28-40 (1)
28-40: Change all filter options to "Required: No".The table marks all filter options (lines 31–40) as "Required: Yes," but the examples section contradicts this:
- Line 47 runs the command with zero filters
- Lines 53, 59, 71, 77, 83, 89 each use individual filters in isolation
All filter options must be optional to match the documented usage. Update the "Required" column to "No" for
--projectId,--deploymentId,--trigger,--env,--threadId,--agentIdentifier,--devmode,--success,--startAfter, and--startBefore.doc-agents/.agents/skills/agentuity-cli-cloud-scp-upload/SKILL.md-17-20 (1)
17-20: Clarify the "cloud deploy" prerequisite.Line 20 lists "cloud deploy" as a prerequisite, but it is unclear what this means:
- Is it a command to run beforehand (e.g.,
agentuity cloud deploy)?- A requirement for an active deployment to exist?
- A service/feature name within Agentuity?
Please provide more context so users understand this dependency.
doc-agents/.agents/skills/agentuity-cli-cloud-scp-upload/SKILL.md-30-33 (1)
30-33: Provide descriptions for Arguments table.Lines 32–33 show empty descriptions (
-) for both<source>and<destination>. Please add meaningful descriptions to help users understand what each argument does. For example:
<source>: Local file path to upload<destination>: Remote destination path (defaults to home directory if omitted)🔎 Example fix for argument descriptions
| Argument | Type | Required | Description | |----------|------|----------|-------------| -| `<source>` | string | Yes | - | -| `<destination>` | string | No | - | +| `<source>` | string | Yes | Local file path to upload | +| `<destination>` | string | No | Remote destination path (defaults to home directory if omitted) |doc-agents/.agents/skills/agentuity-cli-cloud-scp-upload/SKILL.md-22-26 (1)
22-26: Update usage syntax to reflect required--identifierflag.The usage syntax shows
[options]as optional, but line 39 marks--identifieras Required. This should be clarified in the usage line—for example:agentuity cloud scp upload <source> [destination] --identifier=<id>or similar, matching your CLI convention. Additionally, the examples should be updated to consistently show--identifierin all cases, as several examples (lines 46, 52, 64) demonstrate the command without it, contradicting the Required designation.doc-agents/agentuity.json-12-12 (1)
12-12: Verify the region value.The region is set to
"use", which does not match standard cloud region naming conventions (e.g.,us-east-1,us-west-2,eu-west-1). Verify this is the intended value or correct it to a valid region identifier..github/workflows/sync-docs-full.yml-5-5 (1)
5-5: Reconsider running full docs sync on every pull request.Adding a
pull_requesttrigger means this workflow will execute a full documentation sync on every PR. This raises several concerns:
- Performance: Full syncs process all files and could be slow/resource-intensive for every PR
- Data pollution: PR branch content may be synced to the vector store, potentially polluting production data
- Cost: If using OpenAI embeddings, this could incur significant costs for every PR
Consider one of these alternatives:
- Remove the
pull_requesttrigger and keep onlyworkflow_dispatchfor manual full syncs- Add conditions to only run on specific PR labels or paths
- Use a separate test/staging vector store for PR environments
doc-agents/.agents/skills/agentuity-cli-cloud-db-list/SKILL.md-29-32 (1)
29-32: Incorrect "Required" designation for optional flags.Both flags are marked as "Required: Yes," but boolean options like these are universally optional in CLI design. Line 31's description explicitly mentions a default behavior ("masked in terminal"). Update the "Required" column to "No" or remove it entirely if defaults apply.
doc-agents/.agents/skills/agentuity-cli-cloud-deployment-logs/SKILL.md-68-70 (1)
68-70: Document the output array structure and field types.The output section only states "Returns:
array" without specifying:
- What each array element contains
- The structure/type of log entries (timestamps, log levels, messages, etc.)
- Example output format
Compare this to the comprehensive output documentation in other skills (e.g.,
cloud-agent-get).🔎 Suggested improvement approach
## Output -Returns: `array` +Returns JSON array of log entries: + +```json +[ + { + "timestamp": "string (ISO 8601)", + "level": "string (INFO, WARN, ERROR, DEBUG)", + "message": "string", + "source": "string (optional)" + } +] +``` + +| Field | Type | Description | +|-------|------|-------------| +| `timestamp` | string | ISO 8601 formatted timestamp of the log entry. | +| `level` | string | Log level: INFO, WARN, ERROR, or DEBUG. | +| `message` | string | The log message content. | +| `source` | string | Optional source identifier (e.g., component name). |doc-agents/.agents/skills/agentuity-cli-cloud-apikey-get/SKILL.md-1-39 (1)
1-39: Add comprehensive Output section documentation.This skill file is missing the Output section entirely, whereas comparable skill files (e.g.,
cloud-agent-get,cloud-deployment-logs) document the returned JSON structure and field types. This leaves users unable to understand what data the command returns.Add an Output section that includes:
- JSON example output structure
- Field definitions and descriptions
- Data types for each field
- Whether fields are always present or conditional
🔎 Suggested improvement approach
+## Output + +Returns JSON object: + +```json +{ + "id": "string", + "value": "string", + "name": "string", + "createdAt": "string", + "updatedAt": "string", + "lastUsedAt": "string" +} +``` + +| Field | Type | Description | +|-------|------|-------------| +| `id` | string | Unique identifier of the API key. | +| `value` | string | The API key value. Only returned on creation; otherwise redacted. | +| `name` | string | User-provided name for the API key. | +| `createdAt` | string | ISO 8601 timestamp when the key was created. | +| `updatedAt` | string | ISO 8601 timestamp of the last update. | +| `lastUsedAt` | string | ISO 8601 timestamp of last usage, if available. |doc-agents/.agents/skills/agentuity-cli-cloud-agent-get/SKILL.md-47-77 (1)
47-77: Document output fields with actionable descriptions.The output schema describes multiple fields as "unknown" types and includes only "-" placeholders for field descriptions. This leaves users uncertain about the structure and purpose of the returned data.
Consider clarifying:
- What each field represents (e.g.,
identifiervsid, purpose ofmetadata)- What "unknown" types actually contain (objects, any type, or undefined?)
- Whether fields are always present or conditionally returned
🔎 Suggested improvement approach
-| `description` | unknown | - | +| `description` | string | User-provided description of the agent. May be null if not set. | -| `deploymentId` | unknown | - | +| `deploymentId` | string | ID of the currently active deployment, if any. | -| `metadata` | unknown | - | +| `metadata` | object | Custom metadata key-value pairs associated with the agent. | +| `devmode` | boolean | Indicates whether the agent is in development mode. |Committable suggestion skipped: line range outside the PR's diff.
doc-agents/.agents/skills/agentuity-cli-cloud-stream-get/SKILL.md-34-38 (1)
34-38: Incomplete options documentation and incorrect Required value.The
--outputoption is marked as Required: Yes, but this appears to be incorrect—users should be able to run the command without downloading to a file. Additionally, example at line 51 uses--jsonflag, which is not documented in the Options table. Add missing options to the table and correct the Required value for--output.🔎 Proposed fix for options section
## Options | Option | Type | Required | Default | Description | |--------|------|----------|---------|-------------| -| `--output` | string | Yes | - | download stream content to file | +| `--output` | string | No | - | download stream content to file | +| `--json` | boolean | No | - | output as JSON |doc-agents/.agents/skills/agentuity-cli-cloud-stream-list/SKILL.md-29-34 (1)
29-34: Fix contradictory option requirements.All options are marked as "Required: Yes" but their descriptions mention defaults (e.g., "default: 100" for
--size). If defaults exist, these options should be marked as "Required: No". This contradiction will confuse users.🔎 Suggested fix
| Option | Type | Required | Default | Description | |--------|------|----------|---------|-------------| -| `--size` | number | Yes | - | maximum number of streams to return (default: 100) | -| `--offset` | number | Yes | - | number of streams to skip for pagination | -| `--name` | string | Yes | - | filter by stream name | -| `--metadata` | string | Yes | - | filter by metadata (format: key=value or key1=value1,key2=value2) | +| `--size` | number | No | 100 | maximum number of streams to return | +| `--offset` | number | No | 0 | number of streams to skip for pagination | +| `--name` | string | No | - | filter by stream name | +| `--metadata` | string | No | - | filter by metadata (format: key=value or key1=value1,key2=value2) |doc-agents/.agents/skills/agentuity-cli-cloud-apikey-list/SKILL.md-30-31 (1)
30-31: Clarify required options and update prerequisites.The options table marks both
--orgIdand--projectIdas "Required: Yes", but the Prerequisites section (line 18) only mentions authentication. If these options are truly required, the Prerequisites should reflect the need for organization and project context. If they're optional filters, mark them as "Required: No".🔎 Suggested fix if options are optional filters
| Option | Type | Required | Default | Description | |--------|------|----------|---------|-------------| -| `--orgId` | string | Yes | - | filter by organization id | -| `--projectId` | string | Yes | - | filter by project id | +| `--orgId` | string | No | - | filter by organization id | +| `--projectId` | string | No | - | filter by project id |doc-agents/app.ts-3-15 (1)
3-15: Add error handling and consider implementing setup/shutdown logic.The top-level await for
createApphas no error handling, which means any initialization failures will result in unhandled promise rejections. Additionally, bothsetupandshutdowncallbacks are empty placeholders—if this is intentional scaffolding, consider adding TODO comments or basic error handling structure.🔎 Suggested improvements
+try { const { server, logger } = await createApp({ setup: async () => { // anything you return from this will be automatically // available in the ctx.app. this allows you to initialize // global resources and make them available to routes and // agents in a typesafe way + // TODO: Add initialization logic + return {}; }, shutdown: async (_state) => { // the state variable will be the same value was what you // return from setup above. you can use this callback to // close any resources or other shutdown related tasks + // TODO: Add cleanup logic }, }); logger.debug('Running %s', server.url); +} catch (error) { + console.error('Failed to start application:', error); + process.exit(1); +}Committable suggestion skipped: line range outside the PR's diff.
doc-agents/.agents/skills/agentuity-cli-cloud-db-logs/SKILL.md-34-48 (1)
34-48: Fix documentation of required options.Options on lines 38-42 are marked as "Required: Yes" (--startDate, --endDate, --username, --command, --hasError, --sessionId), but the example on line 55 shows the command working without any of these parameters:
agentuity cloud db logs my-database. These should be marked as optional filters, not required options.🔎 Proposed fix
Update the "Required" column for filter options to "No":
| `--startDate` | string | Yes | - | Start date for filtering logs | + | `--startDate` | string | No | - | Start date for filtering logs |Apply the same change to
--endDate,--username,--command,--hasError, and--sessionId.Committable suggestion skipped: line range outside the PR's diff.
doc-agents/.agents/skills/agentuity-cli-cloud-db-create/SKILL.md-41-45 (1)
41-45: Clarify or remove the alternate command example.Line 44 shows
agentuity cloud db newas an example, but the declared command isagentuity cloud db create. Ifnewis an unsupported alias or undocumented command, this example will mislead users and agents. Either document it as an alias or replace it with a valid example.🔎 Proposed fix (if `new` is not a real alias)
Run new command: ```bash -agentuity cloud db new +agentuity cloud db create --name my-db</details> </blockquote></details> <details> <summary>doc-agents/.agents/skills/agentuity-cli-cloud-db-create/SKILL.md-29-39 (1)</summary><blockquote> `29-39`: **Resolve contradictory required/optional status for `--name` option.** Line 31 declares `--name` as required (`Required: Yes`), but line 38 shows an example (`agentuity cloud db create`) that runs without providing the option. Clarify whether `--name` is truly required, optional, or becomes required under specific conditions. <details> <summary>🔎 Potential fixes (choose one based on actual behavior)</summary> **Option A: If --name is optional:** ```diff | Option | Type | Required | Default | Description | |--------|------|----------|---------|-------------| -| `--name` | string | Yes | - | Custom database name | +| `--name` | string | No | - | Custom database name |Option B: If --name is required:
Create new item: ```bash -agentuity cloud db create +agentuity cloud db create --name <database-name></details> > Committable suggestion skipped: line range outside the PR's diff. </blockquote></details> <details> <summary>doc-agents/.agents/skills/agentuity-cli-auth-ssh-add/SKILL.md-26-56 (1)</summary><blockquote> `26-56`: **Clarify the optional/required nature of `--file` and document usage modes.** Line 30 declares `--file` as required (`Required: Yes`), but the interactive example (line 34-38) shows the command running without `--file`. This indicates the flag is optional when using interactive mode. The documentation needs to clarify the two usage modes: 1. Interactive mode (no flags required) 2. File-based mode (--file used to specify source) Currently, the Options table doesn't reflect this optionality. <details> <summary>🔎 Proposed fix</summary> ```diff | Option | Type | Required | Default | Description | |--------|------|----------|---------|-------------| -| `--file` | string | Yes | - | File containing the public key | +| `--file` | string | No | stdin or interactive | File containing the public key (omit for interactive prompt or stdin) |Alternatively, add a note under Usage to clarify the modes:
## Usage ```bash agentuity auth ssh add [options]
+Usage modes:
+- Interactive: Run without options to be prompted for the key
+- File-based: Use--fileto read the public key from a file
+- Stdin: Pipe the key via stdin</details> </blockquote></details> <details> <summary>doc-agents/package.json-23-23 (1)</summary><blockquote> `23-23`: **Update langchain to at least 0.3.80 or later to address known vulnerabilities and runtime issues.** LangChain 0.3.28 has a documented template-injection vulnerability in langchain-core and reported runtime/integration issues. Upgrade to 0.3.80+ or the latest stable release. The caret pinning (^0.3.28) allows patch updates, but starting from a vulnerable base version creates unnecessary risk. </blockquote></details> <details> <summary>doc-agents/src/api/process-docs/index.ts-2-2 (1)</summary><blockquote> `2-2`: **Remove unused import.** The `docProcessingAgent` import is not used in this file. Based on the AI summary, the actual document processing logic appears to be in the related `route.ts` file. <details> <summary>🔎 Proposed fix</summary> ```diff import { createRouter } from '@agentuity/runtime'; -import docProcessingAgent from '@agent/doc_processing/agent'; const router = createRouter();doc-agents/.agents/skills/agentuity-cli-cloud-storage-upload/SKILL.md-35-40 (1)
35-40: Fix inconsistent Required/Default designations in Options table.The Options table marks both options as "Required: Yes" and "Default: -", but their descriptions contradict this:
--key(line 39): Description states "defaults to basename or 'stdin'", so it should not be marked Required.--contentType(line 40): Description states "auto-detected if not provided", so it should not be marked Required.Update the Required and Default columns to match the actual behavior described.
doc-agents/.agents/skills/agentuity-cli-project-show/SKILL.md-58-77 (1)
58-77: Replace "unknown" type annotations with specific types.The Output schema lists
descriptionandtagsfields with type "unknown" (lines 61, 62, 73, 74). This is ambiguous for API consumers or agents using this documentation.Specify the actual types: Are they strings? Arrays? Objects? Optional or required? Update the schema and field descriptions with concrete type information.
doc-agents/.agents/skills/agentuity-cli-cloud-keyvalue-delete-namespace/SKILL.md-28-33 (1)
28-33: Document argument descriptions and clarify<confirm>behavior.The Arguments table shows empty descriptions for both arguments. Specifically:
<confirm>(line 33) lacks documentation of expected values or behavior.Looking at the Examples (lines 40, 46, 52),
<confirm>appears to support multiple forms:
- Interactive (line 40: no argument provided)
- Flag-style (lines 46, 52:
--confirm)Clarify whether
<confirm>is positional or flag-based, and update the Arguments table with specific accepted values or behavior.doc-agents/.agents/skills/agentuity-cli-cloud-env-list/SKILL.md-47-49 (1)
47-49: Complete the Output section.The Output section is incomplete compared to the structure of other skill documentation files. It should include a JSON schema example and a table describing the returned fields, similar to the format used in agentuity-cli-cloud-vector-search and agentuity-cli-cloud-env-import.
doc-agents/.agents/skills/agentuity-cli-cloud-vector-search/SKILL.md-35-41 (1)
35-41: Clarify which options are required vs. optional.The Options table marks
--limit,--similarity, and--metadataas all Required: "Yes", but the descriptions and defaults suggest they should be optional. For example,--limitincludes "(default: 10)", implying it's not required for the command to work.Correct the Required column to accurately reflect whether these options must be provided or can be omitted.
🔎 Proposed fix for the options table
| Option | Type | Required | Default | Description | |--------|------|----------|---------|-------------| - | `--limit` | number | Yes | - | maximum number of results to return (default: 10) | - | `--similarity` | number | Yes | - | minimum similarity threshold (0.0-1.0) | - | `--metadata` | string | Yes | - | filter by metadata (format: key=value or key1=value1,key2=value2) | + | `--limit` | number | No | 10 | maximum number of results to return | + | `--similarity` | number | No | - | minimum similarity threshold (0.0-1.0) | + | `--metadata` | string | No | - | filter by metadata (format: key=value or key1=value1,key2=value2) |doc-agents/.agents/skills/agentuity-cli-cloud-vector-search/SKILL.md-43-73 (1)
43-73: Inconsistent command syntax in examples.The examples use varying command prefixes that don't match the documented usage (
agentuity cloud vector search). Line 48 usesagentuity vector search, line 54 usesagentuity vector list, line 60 usesagentuity vector search, and line 72 usesagentuity vector ls embeddings—all missing the "cloud" prefix or using incorrect subcommands.Ensure all examples follow the correct command syntax:
agentuity cloud vector search.🔎 Proposed fixes for example commands
- Search for similar products: - - ```bash - agentuity vector search products "comfortable office chair" - ``` + Search for similar products: + + ```bash + agentuity cloud vector search products "comfortable office chair" + ``` - Search knowledge base: - - ```bash - agentuity vector list knowledge-base "machine learning" - ``` + Search knowledge base: + + ```bash + agentuity cloud vector search knowledge-base "machine learning" + ``` - Limit results: - - ```bash - agentuity vector search docs "API documentation" --limit 5 - ``` + Limit results: + + ```bash + agentuity cloud vector search docs "API documentation" --limit 5 + ``` - Filter by metadata: - - ```bash - agentuity vector ls embeddings "neural networks" --metadata category=ai - ``` + Filter by metadata: + + ```bash + agentuity cloud vector search embeddings "neural networks" --metadata category=ai + ```Committable suggestion skipped: line range outside the PR's diff.
doc-agents/src/api/process-docs/route.ts-7-11 (1)
7-11: Add error handling and consider webhook authentication.The endpoint directly awaits
docProcessingAgent.run()without error handling. If the agent throws an exception, it may result in unclear error responses or unhandled rejections.Additionally, since this endpoint is called from CI workflows (per the AI summary), consider adding webhook signature verification to prevent unauthorized requests.
🔎 Proposed fix with error handling
router.post('/', docProcessingAgent.validator(), async (c) => { const data = c.req.valid('json'); - const result = await docProcessingAgent.run(data); - return c.json(result); + try { + const result = await docProcessingAgent.run(data); + return c.json(result); + } catch (error) { + console.error('Doc processing failed:', error); + return c.json({ success: false, error: 'Processing failed' }, 500); + } });doc-agents/.agents/skills/agentuity-cli-cloud-storage-get/SKILL.md-38-38 (1)
38-38: Fix contradictory requirement for--showCredentials.The
--showCredentialsoption is marked asRequired: Yes, but the description indicates default behavior (masked in terminal, unmasked in JSON), which implies the option is optional. If it's optional with default behavior, changeRequiredtoNo.🔎 Proposed fix
| Option | Type | Required | Default | Description | |--------|------|----------|---------|-------------| -| `--showCredentials` | boolean | Yes | - | Show credentials in plain text (default: masked in terminal, unmasked in JSON) | +| `--showCredentials` | boolean | No | `false` | Show credentials in plain text (default: masked in terminal, unmasked in JSON) |doc-agents/.agents/skills/agentuity-cli-cloud-thread-list/SKILL.md-29-32 (1)
29-32: Fix inconsistencies in the options table.The options table has several issues:
Contradictory requirements:
--orgIdand--projectIdare marked asRequired: Yes, but the examples (lines 36-40) show the command working without these options, and lines 48-58 show them as optional filters.Naming inconsistency: The table uses camelCase (
--orgId,--projectId), but the examples use kebab-case (--project-id,--org-id). Verify the correct format and make them consistent.Invalid default value: Having
Required: YeswithDefault: -is contradictory. If they're required, they shouldn't have defaults; if they're optional, mark them asNo.🔎 Proposed fix
| Option | Type | Required | Default | Description | |--------|------|----------|---------|-------------| | `--count` | number | No | `10` | Number of threads to list (1–100) | -| `--orgId` | string | Yes | - | Filter by organization ID | -| `--projectId` | string | Yes | - | Filter by project ID | +| `--org-id` | string | No | - | Filter by organization ID | +| `--project-id` | string | No | - | Filter by project ID |doc-agents/.agents/skills/agentuity-cli-profile-create/SKILL.md-32-33 (1)
32-33: Fix contradictory requirement for--switch.The
--switchoption is marked asRequired: Yes, but:
- The description says "switch to this profile (if more than one)", which implies conditional/optional behavior
- The first example (lines 37-41) shows the command working without this flag
This should be marked as
Required: Nosince it's an optional flag.🔎 Proposed fix
| Option | Type | Required | Default | Description | |--------|------|----------|---------|-------------| -| `--switch` | boolean | Yes | - | switch to this profile (if more than one) | +| `--switch` | boolean | No | `false` | Switch to this profile after creation |doc-agents/.agents/skills/agentuity-cli-cloud-vector-upsert/SKILL.md-36-42 (1)
36-42: Fix mutually exclusive options marked as required.All options (
--document,--embeddings,--metadata,--file) are marked asRequired: Yes, but they appear to be mutually exclusive based on the examples:
- Lines 46-50: Use
--documentalone- Lines 58-62: Use
--embeddingsalone- Lines 64-74: Use
--filealoneIf these options are mutually exclusive (you use one OR another), they should be marked as
Required: Nowith a note explaining which combination is valid, or restructure the table to clarify the mutual exclusivity.🔎 Proposed fix
| Option | Type | Required | Default | Description | |--------|------|----------|---------|-------------| -| `--document` | string | Yes | - | document text to embed | -| `--embeddings` | string | Yes | - | pre-computed embeddings as JSON array | -| `--metadata` | string | Yes | - | metadata as JSON object | -| `--file` | string | Yes | - | path to JSON file containing vectors, or "-" for stdin | +| `--document` | string | No | - | Document text to embed (mutually exclusive with --embeddings and --file) | +| `--embeddings` | string | No | - | Pre-computed embeddings as JSON array (mutually exclusive with --document and --file) | +| `--metadata` | string | No | - | Metadata as JSON object (can be combined with --document or --embeddings) | +| `--file` | string | No | - | Path to JSON file containing vectors, or "-" for stdin (mutually exclusive with --document and --embeddings) |doc-agents/.agents/skills/agentuity-cli-cloud-storage-get/SKILL.md-48-52 (1)
48-52: Fix the incorrect subcommand in the example.Line 51 uses
agentuity cloud storage show my-bucket, but the documented command isagentuity cloud storage get. Changeshowtogetto match the command syntax defined in the metadata (line 9) and usage section (line 25).agentuity cloud storage get my-bucketdoc-agents/src/agent/doc_processing/chunk-mdx.ts-146-147 (1)
146-147: Handle potentially undefined frontmatter fields.
frontmatter.titleandfrontmatter.descriptionmay beundefinedif the MDX file lacks these fields, but theChunktype requires them asstring. This mismatch can cause downstream issues when processing chunks that expect string values.🔎 Proposed fix with fallback values
return { id: crypto.randomUUID(), chunkIndex: idx, totalChunks: chunks.length, contentType: chunk.metadata.contentType, heading: currentHeading, text: chunk.pageContent, - title: frontmatter.title, - description: frontmatter.description, + title: frontmatter.title ?? '', + description: frontmatter.description ?? '', createdAt: new Date().toISOString(), };Alternatively, update the
Chunktype to maketitleanddescriptionoptional (title?: string), depending on how downstream consumers handle these fields.doc-agents/.agents/skills/agentuity-cli-cloud-redis-show/SKILL.md-31-31 (1)
31-31: Clarify whether--showCredentialsis required or optional.The Options table marks
--showCredentialsas "Required: Yes" (line 31), but the basic example on lines 38-39 demonstrates the command without this option. Either the option is optional (and the table should reflect this), or the basic example is incomplete. Correct the documentation to accurately reflect the command's behavior.Also applies to: 38-39
doc-agents/.agents/skills/agentuity-cli-cloud-redis-show/SKILL.md-29-32 (1)
29-32: Fix option naming inconsistency and required status declaration.The Options table lists the option as
--showCredentials(camelCase) on line 31, but the example on line 44 uses--show-credentials(kebab-case). Additionally, the option is marked "Required: Yes" yet the first example on line 38 successfully executes the command without it. Align the option name in the table to match the examples and correct the required status to reflect actual usage.
| | Option | Type | Required | Default | Description | | ||
| |--------|------|----------|---------|-------------| | ||
| | `--deploymentId` | string | Yes | - | Filter by deployment ID | | ||
| | `--verbose` | boolean | No | `false` | Show full descriptions | |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🧩 Analysis chain
🏁 Script executed:
cat -n "doc-agents/.agents/skills/agentuity-cli-cloud-agent-list/SKILL.md"Repository: agentuity/docs
Length of output: 1463
Resolve contradiction between required --deploymentId parameter and usage examples.
The options table marks --deploymentId as required, but all three examples (lines 38, 44, and 50) execute the command without this parameter. If --deploymentId is truly required, these examples would fail. Either mark the flag as optional in the table with context for when filtering is useful, or update all examples to include it.
Additionally, the output documentation (line 55) only states Returns: array without describing the structure or properties of the returned elements.
🤖 Prompt for AI Agents
In doc-agents/.agents/skills/agentuity-cli-cloud-agent-list/SKILL.md around
lines 28 to 31, the options table incorrectly marks `--deploymentId` as required
while all examples omit it; either update the table to mark `--deploymentId` as
optional and add a short note about when to use it (e.g., "Optional — use to
filter results to a specific deployment"), or update all three usage examples to
include a realistic `--deploymentId <id>` value so they match the required flag;
additionally, expand the "Returns: array" output documentation (line ~55) to
list the object schema of each array element (field names, types and brief
descriptions such as id, name, deploymentId, status, createdAt) so callers know
what properties to expect.
| | Option | Type | Required | Default | Description | | ||
| |--------|------|----------|---------|-------------| | ||
| | `--showCredentials` | boolean | Yes | - | Show credentials in plain text (default: masked in terminal, unmasked in JSON) | | ||
| | `--nameOnly` | boolean | Yes | - | Print the name only | |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Critical: Inconsistent option naming convention between documentation and examples.
CLI documentation should consistently use kebab-case for option names, but the options table (lines 29-32) lists --showCredentials (camelCase) while the example (line 57) shows --show-credentials (kebab-case). Users won't know which syntax to use.
🔎 Proposed fix
Standardize on kebab-case throughout the documentation:
| Option | Type | Required | Default | Description |
|--------|------|----------|---------|-------------|
-| `--showCredentials` | boolean | Yes | - | Show credentials in plain text (default: masked in terminal, unmasked in JSON) |
-| `--nameOnly` | boolean | Yes | - | Print the name only |
+| `--show-credentials` | boolean | No | false | Show credentials in plain text (default: masked in terminal, unmasked in JSON) |
+| `--name-only` | boolean | No | false | Print the name only |Also applies to: 57-57
🤖 Prompt for AI Agents
In doc-agents/.agents/skills/agentuity-cli-cloud-db-list/SKILL.md around lines
29 to 32 (and also update line 57), the options table uses camelCase
(`--showCredentials`) while examples use kebab-case (`--show-credentials`);
standardize option naming to kebab-case across the doc by renaming
`--showCredentials` to `--show-credentials` in the table, and verify other
options (e.g., `--nameOnly`) are converted to `--name-only` so the examples and
documentation match.
| Run pull command: | ||
|
|
||
| ```bash | ||
| agentuity env pull | ||
| ``` | ||
|
|
||
| Use force option: | ||
|
|
||
| ```bash | ||
| agentuity env pull --force | ||
| ``` |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Fix incorrect command in examples.
The examples show agentuity env pull but should be agentuity cloud env pull to match the documented command in the YAML metadata (line 8) and usage section (line 25).
🔎 Proposed fix
Run pull command:
```bash
-agentuity env pull
+agentuity cloud env pullUse force option:
-agentuity env pull --force
+agentuity cloud env pull --force</details>
<details>
<summary>🤖 Prompt for AI Agents</summary>
In doc-agents/.agents/skills/agentuity-cli-cloud-env-pull/SKILL.md around lines
36 to 46, the example commands use the incorrect invocation "agentuity env
pull"; update both examples to use "agentuity cloud env pull" (and the force
variant "agentuity cloud env pull --force") so they match the YAML metadata and
usage section. Ensure the two code blocks are replaced accordingly and keep
formatting consistent with surrounding markdown.
</details>
<!-- fingerprinting:phantom:poseidon:puma -->
<!-- This is an auto-generated comment by CodeRabbit -->
|
|
||
| | Option | Type | Required | Default | Description | | ||
| |--------|------|----------|---------|-------------| | ||
| | `--identifier` | string | Yes | - | The project or deployment id to use | |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🧩 Analysis chain
🏁 Script executed:
cat -n "doc-agents/.agents/skills/agentuity-cli-cloud-scp-upload/SKILL.md" | sed -n '35,65p'Repository: agentuity/docs
Length of output: 864
--identifier is marked Required but omitted from 3 of 4 examples.
The Options table (line 39) declares --identifier as Required: "Yes", yet Examples 1, 2, and 4 (lines 46, 52, 64) show commands without this flag. Either the parameter is optional and should be marked accordingly in the table, or all examples must include it.
🤖 Prompt for AI Agents
In doc-agents/.agents/skills/agentuity-cli-cloud-scp-upload/SKILL.md around line
39, the Options table marks `--identifier` as required but three of the four
examples omit it; update the file so the docs are consistent by either (A) if
the flag is optional, change the table entry to "No" and add a short note
describing the default behavior, or (B) if the flag is required, add
`--identifier <value>` to Examples 1, 2, and 4 so every example includes the
required flag; choose the correct truth and apply the corresponding change
consistently across the table and examples.
| ## Usage | ||
|
|
||
| ```bash | ||
| agentuity cloud secret delete <key> |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
User-facing examples do not match documented usage.
The usage section specifies agentuity cloud secret delete <key> (line 25), but the examples use different command patterns:
- Line 39:
agentuity secret delete(omitscloud) - Line 45:
agentuity secret rm(uses undocumentedrmalias and omitscloud)
Ensure the examples match the documented usage, or clarify if these are supported aliases. Users following this documentation may encounter unexpected failures if the examples don't work as written.
🔎 Proposed fix to align examples with documented usage
Delete item:
```bash
-agentuity secret delete OLD_API_KEY
+agentuity cloud secret delete OLD_API_KEYDelete item:
-agentuity secret rm DATABASE_URL
+agentuity cloud secret delete DATABASE_URL</details>
Also applies to: 39-39, 45-45
<details>
<summary>🤖 Prompt for AI Agents</summary>
In doc-agents/.agents/skills/agentuity-cli-cloud-secret-delete/SKILL.md around
lines 25, 39 and 45, the examples do not match the documented usage which lists
the command as "agentuity cloud secret delete "; update the example
commands to use that exact form (replace occurrences of "agentuity secret delete
OLD_API_KEY" and "agentuity secret rm DATABASE_URL" with "agentuity cloud secret
delete OLD_API_KEY" and "agentuity cloud secret delete DATABASE_URL"
respectively), or alternatively add a brief note that the shorter alias and "rm"
are supported and document those aliases explicitly if they are valid.
</details>
<!-- fingerprinting:phantom:triton:mongoose -->
<!-- This is an auto-generated comment by CodeRabbit -->
| ## Examples | ||
|
|
||
| Get stream details: | ||
|
|
||
| ```bash | ||
| agentuity stream get stream-id-123 | ||
| ``` | ||
|
|
||
| Get stream as JSON: | ||
|
|
||
| ```bash | ||
| agentuity stream get stream-id-123 --json | ||
| ``` | ||
|
|
||
| Download stream to file: | ||
|
|
||
| ```bash | ||
| agentuity stream get stream-id-123 --output stream.dat | ||
| ``` | ||
|
|
||
| Download stream (short flag): | ||
|
|
||
| ```bash | ||
| agentuity stream get stream-id-123 -o stream.dat | ||
| ``` |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Examples are missing the "cloud" command prefix.
All four examples (lines 45, 51, 57, 63) show commands like agentuity stream get ..., but the metadata command and usage section specify agentuity cloud stream get. Users following these examples will run incorrect commands. Update all examples to include the "cloud" keyword.
🔎 Proposed fix for examples
Get stream details:
```bash
-agentuity stream get stream-id-123
+agentuity cloud stream get stream-id-123Get stream as JSON:
-agentuity stream get stream-id-123 --json
+agentuity cloud stream get stream-id-123 --jsonDownload stream to file:
-agentuity stream get stream-id-123 --output stream.dat
+agentuity cloud stream get stream-id-123 --output stream.datDownload stream (short flag):
-agentuity stream get stream-id-123 -o stream.dat
+agentuity cloud stream get stream-id-123 -o stream.dat</details>
<!-- suggestion_start -->
<details>
<summary>📝 Committable suggestion</summary>
> ‼️ **IMPORTANT**
> Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
```suggestion
## Examples
Get stream details:
🤖 Prompt for AI Agents
In doc-agents/.agents/skills/agentuity-cli-cloud-stream-get/SKILL.md around
lines 40 to 64, the four example commands omit the required "cloud" subcommand
(they use "agentuity stream get ..."); update each example to use "agentuity
cloud stream get ..." (so replace "agentuity stream get stream-id-123" with
"agentuity cloud stream get stream-id-123", and likewise add "cloud" for the
--json, --output, and -o variants) ensuring all example blocks and any
surrounding text reflect the corrected command.
| ## Examples | ||
|
|
||
| Delete staging namespace (interactive): | ||
|
|
||
| ```bash | ||
| agentuity vector delete-namespace staging | ||
| ``` | ||
|
|
||
| Delete cache without confirmation: | ||
|
|
||
| ```bash | ||
| agentuity vector rm-namespace cache --confirm | ||
| ``` | ||
|
|
||
| Force delete old-data namespace: | ||
|
|
||
| ```bash | ||
| agentuity vector delete-namespace old-data --confirm | ||
| ``` |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Examples contain two critical command errors.
-
All three examples (lines 45, 51, 57) are missing the "cloud" keyword (should be
agentuity cloud vector delete-namespace, notagentuity vector delete-namespace). -
Line 51 uses
agentuity vector rm-namespaceinstead of the documenteddelete-namespacesubcommand. Ifrm-namespaceis an alias, it should be documented in the options or commands section; otherwise, this example is incorrect.
Both errors will cause users following the examples to run wrong commands.
🔎 Proposed fix for examples
Delete staging namespace (interactive):
```bash
-agentuity vector delete-namespace staging
+agentuity cloud vector delete-namespace stagingDelete cache without confirmation:
-agentuity vector rm-namespace cache --confirm
+agentuity cloud vector delete-namespace cache --confirmForce delete old-data namespace:
-agentuity vector delete-namespace old-data --confirm
+agentuity cloud vector delete-namespace old-data --confirm</details>
<details>
<summary>🤖 Prompt for AI Agents</summary>
In
doc-agents/.agents/skills/agentuity-cli-cloud-vector-delete-namespace/SKILL.md
around lines 40 to 58, the three example commands are incorrect: they omit the
required "cloud" subcommand and one example uses the wrong subcommand alias
"rm-namespace". Update the three examples to use "agentuity cloud vector
delete-namespace ..." (replace the staging, cache, and old-data examples
accordingly) and change "agentuity vector rm-namespace cache --confirm" to
"agentuity cloud vector delete-namespace cache --confirm"; if "rm-namespace" is
a supported alias, instead add a note in the commands/options section
documenting the alias and still show the canonical "delete-namespace" example
here.
</details>
<!-- fingerprinting:phantom:triton:mongoose -->
<!-- This is an auto-generated comment by CodeRabbit -->
| | Option | Type | Required | Default | Description | | ||
| |--------|------|----------|---------|-------------| | ||
| | `--name` | string | Yes | - | Project name | | ||
| | `--dir` | string | Yes | - | Directory to create the project in | | ||
| | `--domains` | array | Yes | - | Array of custom domains | | ||
| | `--template` | string | Yes | - | Template to use | | ||
| | `--templateDir` | string | Yes | - | Local template directory for testing (e.g., ./packages/templates) | | ||
| | `--templateBranch` | string | Yes | - | GitHub branch to use for templates (default: main) | | ||
| | `--install` | boolean | No | `true` | Run bun install after creating the project (use --no-install to skip) | | ||
| | `--build` | boolean | No | `true` | Run bun run build after installing (use --no-build to skip) | | ||
| | `--confirm` | boolean | Yes | - | Skip confirmation prompts | | ||
| | `--register` | boolean | No | `true` | Register the project, if authenticated (use --no-register to skip) | |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🧩 Analysis chain
🏁 Script executed:
# First, let's locate the CLI implementation for agentuity-cli-project-create
fd -t f -e ts -e js -e py 'project' doc-agents/ | head -20Repository: agentuity/docs
Length of output: 40
🏁 Script executed:
# Let's find the main skill directory structure
find doc-agents -type d -name '*project*' 2>/dev/nullRepository: agentuity/docs
Length of output: 273
🏁 Script executed:
# Look for the actual skill implementation
find doc-agents/.agents/skills/agentuity-cli-project-create -type f \( -name "*.ts" -o -name "*.js" -o -name "*.py" \) 2>/dev/nullRepository: agentuity/docs
Length of output: 40
🏁 Script executed:
# Check what files exist in the skill directory
ls -la doc-agents/.agents/skills/agentuity-cli-project-create/ 2>/dev/nullRepository: agentuity/docs
Length of output: 229
🏁 Script executed:
# Let's read the full SKILL.md file to understand the context better
cat -n doc-agents/.agents/skills/agentuity-cli-project-create/SKILL.mdRepository: agentuity/docs
Length of output: 3145
Fix inconsistencies in Required field values in the options table.
The table marks --name, --dir, --domains, --template, --templateDir, --templateBranch, and --confirm as Required: Yes, but line 42 shows a usage example (agentuity project create) that runs with zero arguments. Additionally, --confirm should be Required: No for consistency with other boolean flags like --install and --register. Reconcile the table with the documented examples.
🤖 Prompt for AI Agents
In doc-agents/.agents/skills/agentuity-cli-project-create/SKILL.md around lines
24 to 35, the options table incorrectly marks many flags as "Required: Yes"
despite the usage example showing the command can run with no arguments and
boolean flags being optional; update the Required column to reflect actual CLI
behavior: change `--name`, `--dir`, `--domains`, `--template`, `--templateDir`,
`--templateBranch` to "No" unless the command truly errors without them (verify
against the CLI implementation), and change `--confirm` to "No" (matching other
booleans like `--install` and `--register`); keep the Default column accurate
(e.g., `--templateBranch` default: main) and ensure the table matches the
documented example.
| "projectId": "proj_16bce250db75e8e8db0f303c99397ead", | ||
| "orgId": "org_2u8RgDTwcZWrZrZ3sZh24T5FCtz", |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Remove hardcoded credentials from version control.
The projectId and orgId appear to be real identifiers rather than placeholders. Committing these to version control exposes them to unauthorized access.
Move these values to environment variables or a secrets management system, and reference them via environment variable substitution in the configuration file (e.g., "projectId": "$PROJECT_ID").
🤖 Prompt for AI Agents
In doc-agents/agentuity.json around lines 3 to 4, the projectId and orgId are
hardcoded real identifiers; remove them and replace with environment-variable
references (e.g., read from PROJECT_ID and ORG_ID) or a secrets manager
reference, and update any deployment/launch scripts and documentation to set
those environment variables securely (do not commit actual secrets to VCS).
doc-agents/src/agent/hello/agent.ts
Outdated
| }, | ||
| handler: async (_ctx, { prompt }) => { | ||
| const { text } = await generateText({ | ||
| model: openai('gpt-5-mini'), |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🧩 Analysis chain
🌐 Web query:
current available OpenAI GPT model identifiers January 2026
💡 Result:
Here are OpenAI’s primary GPT model identifiers available as of January 2, 2026 (with representative snapshots/aliases where present):
- gpt-4.1, gpt-4.1-mini, gpt-4.1-nano. [1]
- gpt-4o (alias: gpt-4o and snapshots such as gpt-4o-2024-11-20, gpt-4o-2024-08-06). [2]
- gpt-4o-mini. [3]
Notes: OpenAI’s docs and release notes also list snapshot/legacy names and ongoing deprecations—check the Models/Release Notes pages for full, up-to-date model lists and snapshot aliases. [4]
Sources:
[1] OpenAI — “Introducing GPT-4.1 in the API” (April 14, 2025). (openai.com)
[2] OpenAI Docs — “GPT-4o Model.” (platform.openai.com)
[3] OpenAI Docs — “GPT-4o mini Model.” (platform.openai.com)
[4] OpenAI — Model Release Notes / Deprecations. (help.openai.com)
Citations:
- 1: https://openai.com/index/gpt-4-1//?utm_source=openai
- 2: https://platform.openai.com/docs/models/gpt-4o?utm_source=openai
- 3: https://platform.openai.com/docs/models/gpt-4o-mini?utm_source=openai
- 4: https://help.openai.com/en/articles/9624314-model-release-notes%3F.zst?utm_source=openai
Replace non-existent model identifier 'gpt-5-mini' with a valid OpenAI model.
The model 'gpt-5-mini' does not exist. GPT-5 has not been released as of January 2026. This will cause runtime errors when the agent is invoked.
Recommended fix
- model: openai('gpt-4o-mini'),
+ model: openai('gpt-4o-mini'),Currently available models include gpt-4o-mini, gpt-4o, gpt-4.1, gpt-4.1-mini, and gpt-4.1-nano.
Committable suggestion skipped: line range outside the PR's diff.
🤖 Prompt for AI Agents
In doc-agents/src/agent/hello/agent.ts around line 14, the model identifier
'gpt-5-mini' is invalid and will cause runtime errors; replace it with a
currently available OpenAI model such as 'gpt-4o-mini' (or 'gpt-4.1' /
'gpt-4.1-mini' / 'gpt-4.1-nano' / 'gpt-4o') by updating the openai(...) call to
use one of those valid model names so the agent initializes against a supported
model.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 6
🧹 Nitpick comments (3)
doc-agents/src/agent/doc_processing/docs-orchestrator.ts (3)
20-20: Consider aligning batch size with clearVectorDb.The limit here is 100, while
clearVectorDbuses 1000 (line 149). Unless there's a specific reason for the smaller batch size, consider using a consistent value to simplify maintenance and potentially improve performance.
80-137: Consider parallelizing file processing for better performance.Files are currently processed sequentially, which could be slow for large batches. Since each file's processing is independent (removal, chunking, upserting are all scoped to the file's path), consider using
Promise.allorPromise.allSettledto process multiple files concurrently.🔎 Example parallel processing approach
// Process changed files in parallel with error isolation const fileResults = await Promise.allSettled( changed.map(async (file) => { const { path: logicalPath, content: base64Content } = file; // Base64-decode the content let content: string; try { const buf = Buffer.from(base64Content, 'base64'); const normalized = base64Content.replace(/\s/g, ''); if (buf.toString('base64') !== normalized) { throw new Error('Malformed base64 payload'); } content = buf.toString('utf-8'); } catch (decodeErr) { throw new Error( `Invalid base64 content for ${logicalPath}: ${decodeErr}` ); } // Remove existing vectors for this path await removeVectorsByPath(ctx, logicalPath, VECTOR_STORE_NAME); // Process the document content into chunks const chunks = await processDoc(content); // Add path metadata to all chunks const chunksWithMetadata = chunks.map((chunk) => ({ ...chunk, metadata: { ...chunk.metadata, path: logicalPath, }, })); // Batch upsert all chunks at once for efficiency const upsertResults = await ctx.vector.upsert( VECTOR_STORE_NAME, ...chunksWithMetadata ); ctx.logger.info( 'Upserted %d chunks for file: %s', upsertResults.length, logicalPath ); return { logicalPath, chunks: chunks.length }; }) ); // Process results for (const result of fileResults) { if (result.status === 'fulfilled') { processed++; ctx.logger.info( 'Successfully processed file: %s (%d chunks)', result.value.logicalPath, result.value.chunks ); } else { errors++; const filePath = changed[fileResults.indexOf(result)]?.path || 'unknown'; errorFiles.push(filePath); ctx.logger.error('Error processing file %s: %o', filePath, result.reason); } }Note: Be mindful of rate limits and resource constraints when increasing concurrency.
148-148: Inconsistent query strings across functions.This function uses
query: ' '(space) whileremoveVectorsByPathusesquery: 'A'. If both are arbitrary placeholders required by the API, standardize them or extract to a named constant for clarity.// At the top of the file const METADATA_ONLY_QUERY = 'A'; // Arbitrary query required by vector search API when filtering by metadata only // Then use consistently: const batch = await ctx.vector.search(VECTOR_STORE_NAME, { query: METADATA_ONLY_QUERY, limit: 1000, });
📜 Review details
Configuration used: Organization UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (1)
doc-agents/src/agent/doc_processing/docs-orchestrator.ts
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (1)
- GitHub Check: sync
| while (true) { | ||
| const vectors = await ctx.vector.search(vectorStoreName, { | ||
| query: 'A', | ||
| limit: 100, | ||
| metadata: { path: logicalPath }, | ||
| }); | ||
|
|
||
| if (vectors.length === 0) { | ||
| break; | ||
| } | ||
|
|
||
| // Batch delete all vectors at once for efficiency | ||
| const keys = vectors.map((v: { key: string }) => v.key); | ||
| const deletedCount = await ctx.vector.delete(vectorStoreName, ...keys); | ||
| totalDeleted += deletedCount; | ||
|
|
||
| ctx.logger.info( | ||
| 'Deleted %d vectors (total: %d) for path: %s', | ||
| deletedCount, | ||
| totalDeleted, | ||
| logicalPath | ||
| ); | ||
| } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🛠️ Refactor suggestion | 🟠 Major
Add error handling inside the deletion loop.
The while(true) loop lacks error handling for ctx.vector.search and ctx.vector.delete operations. If these operations fail mid-loop, the function will throw and leave the deletion incomplete, potentially causing inconsistent state.
🔎 Proposed fix with error handling
while (true) {
- const vectors = await ctx.vector.search(vectorStoreName, {
- query: 'A',
- limit: 100,
- metadata: { path: logicalPath },
- });
+ let vectors;
+ try {
+ vectors = await ctx.vector.search(vectorStoreName, {
+ query: 'A',
+ limit: 100,
+ metadata: { path: logicalPath },
+ });
+ } catch (searchErr) {
+ ctx.logger.error('Error searching vectors for path %s: %o', logicalPath, searchErr);
+ throw searchErr;
+ }
if (vectors.length === 0) {
break;
}
// Batch delete all vectors at once for efficiency
const keys = vectors.map((v: { key: string }) => v.key);
- const deletedCount = await ctx.vector.delete(vectorStoreName, ...keys);
+ let deletedCount;
+ try {
+ deletedCount = await ctx.vector.delete(vectorStoreName, ...keys);
+ } catch (deleteErr) {
+ ctx.logger.error('Error deleting vectors for path %s: %o', logicalPath, deleteErr);
+ throw deleteErr;
+ }
totalDeleted += deletedCount;📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| while (true) { | |
| const vectors = await ctx.vector.search(vectorStoreName, { | |
| query: 'A', | |
| limit: 100, | |
| metadata: { path: logicalPath }, | |
| }); | |
| if (vectors.length === 0) { | |
| break; | |
| } | |
| // Batch delete all vectors at once for efficiency | |
| const keys = vectors.map((v: { key: string }) => v.key); | |
| const deletedCount = await ctx.vector.delete(vectorStoreName, ...keys); | |
| totalDeleted += deletedCount; | |
| ctx.logger.info( | |
| 'Deleted %d vectors (total: %d) for path: %s', | |
| deletedCount, | |
| totalDeleted, | |
| logicalPath | |
| ); | |
| } | |
| while (true) { | |
| let vectors; | |
| try { | |
| vectors = await ctx.vector.search(vectorStoreName, { | |
| query: 'A', | |
| limit: 100, | |
| metadata: { path: logicalPath }, | |
| }); | |
| } catch (searchErr) { | |
| ctx.logger.error('Error searching vectors for path %s: %o', logicalPath, searchErr); | |
| throw searchErr; | |
| } | |
| if (vectors.length === 0) { | |
| break; | |
| } | |
| // Batch delete all vectors at once for efficiency | |
| const keys = vectors.map((v: { key: string }) => v.key); | |
| let deletedCount; | |
| try { | |
| deletedCount = await ctx.vector.delete(vectorStoreName, ...keys); | |
| } catch (deleteErr) { | |
| ctx.logger.error('Error deleting vectors for path %s: %o', logicalPath, deleteErr); | |
| throw deleteErr; | |
| } | |
| totalDeleted += deletedCount; | |
| ctx.logger.info( | |
| 'Deleted %d vectors (total: %d) for path: %s', | |
| deletedCount, | |
| totalDeleted, | |
| logicalPath | |
| ); | |
| } |
| const vectors = await ctx.vector.search(vectorStoreName, { | ||
| query: 'A', | ||
| limit: 100, | ||
| metadata: { path: logicalPath }, | ||
| }); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🧩 Analysis chain
🏁 Script executed:
cd doc-agents && find . -name "*.ts" -type f | head -20Repository: agentuity/docs
Length of output: 648
🏁 Script executed:
# Search for vector.search usage and API definition
rg -n "vector\.search" --type=ts -A 3 -B 3Repository: agentuity/docs
Length of output: 3649
🏁 Script executed:
# Look for vector store interface/type definitions
rg -n "interface.*vector|type.*vector" --type=ts -iRepository: agentuity/docs
Length of output: 595
🏁 Script executed:
# Check the context of the removeVectorsByPath function
head -60 src/agent/doc_processing/docs-orchestrator.ts | tail -45Repository: agentuity/docs
Length of output: 162
🏁 Script executed:
# Read the actual file being reviewed
cat -n doc-agents/src/agent/doc_processing/docs-orchestrator.ts | head -60Repository: agentuity/docs
Length of output: 1923
🏁 Script executed:
# Look for any documentation or comments about the query parameter
rg -n "query.*A|query.*space" --type=ts -B 3 -A 3Repository: agentuity/docs
Length of output: 3556
🏁 Script executed:
# Check if there's any API documentation in the project
find . -name "*.md" -o -name "*.txt" | xargs grep -l "vector.search\|query.*parameter" 2>/dev/null | head -5Repository: agentuity/docs
Length of output: 246
🏁 Script executed:
# Look for any additional context about why 'A' might be used vs space
rg -n "query.*:" --type=ts doc-agents/ agent-docs/ | grep -E "(query|search)" | head -20Repository: agentuity/docs
Length of output: 1054
🏁 Script executed:
# Check git history to see if this was a recent change
cd doc-agents && git log -p --follow -S "'A'" -- src/agent/doc_processing/docs-orchestrator.ts 2>/dev/null | head -50Repository: agentuity/docs
Length of output: 40
Use a space placeholder for the query parameter to match the codebase pattern.
The query parameter should be ' ' (space) instead of 'A' to align with the consistent pattern used throughout the codebase. Line 148 in the same file and the parallel agent-docs implementation both use ' ' as a placeholder when the intent is metadata-filtered search without semantic relevance to the query.
Codebase pattern reference
// Line 148 of this same file (correct pattern):
query: ' ',
// agent-docs parallel implementation:
// docs-orchestrator.ts line 20: query: ' ',
// retriever.ts line 52 (metadata-filtered search): query: ' ',
🤖 Prompt for AI Agents
In doc-agents/src/agent/doc_processing/docs-orchestrator.ts around lines 18 to
22, the vector.search call uses query: 'A' which deviates from the project's
placeholder pattern; change the query value to a single space ' ' to match the
metadata-filtered search convention used elsewhere (e.g., line 148 and parallel
agent-docs implementations) so the search behaves consistently with other
metadata-only queries.
| * Process documentation sync from embedded payload - completely filesystem-free | ||
| */ | ||
| export async function syncDocsFromPayload( | ||
| ctx: any, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🛠️ Refactor suggestion | 🟠 Major
Replace any type with proper typing.
Using ctx: any disables type checking and loses IDE support. Define or import a proper context type to improve type safety and maintainability.
// Example: Define or import a context type
interface DocProcessingContext {
logger: Logger;
vector: VectorStore;
// ... other properties
}
export async function syncDocsFromPayload(
ctx: DocProcessingContext,
payload: SyncPayload
): Promise<SyncStats>🤖 Prompt for AI Agents
In doc-agents/src/agent/doc_processing/docs-orchestrator.ts around line 56,
replace the loose ctx: any with a concrete context type: define or import an
interface (e.g., DocProcessingContext) that lists the fields the function
actually uses (logger, vectorStore/VectorStore, db/client, config/options, and
any request or tracing metadata) and update the function signature to use that
type; ensure necessary types are imported from their modules and update any call
sites to satisfy the new type (or cast only at call boundaries), so you restore
type safety and IDE tooling without changing runtime behavior.
| try { | ||
| const buf = Buffer.from(base64Content, 'base64'); | ||
| // re-encode to verify round-trip | ||
| if (buf.toString('base64') !== base64Content.replace(/\s/g, '')) { | ||
| throw new Error('Malformed base64 payload'); | ||
| } | ||
| content = buf.toString('utf-8'); | ||
| } catch (decodeErr) { | ||
| throw new Error( | ||
| `Invalid base64 content for ${logicalPath}: ${decodeErr}` | ||
| ); | ||
| } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Fix the base64 validation logic.
The round-trip validation at line 89 has a logical flaw. The comparison buf.toString('base64') !== base64Content.replace(/\s/g, '') only removes whitespace from the original base64Content, but not from the re-encoded result. This asymmetric comparison could cause false positives or false negatives depending on how Node.js formats the base64 output.
🔎 Proposed fix for symmetric validation
let content: string;
try {
const buf = Buffer.from(base64Content, 'base64');
// re-encode to verify round-trip
- if (buf.toString('base64') !== base64Content.replace(/\s/g, '')) {
+ const normalized = base64Content.replace(/\s/g, '');
+ if (buf.toString('base64') !== normalized) {
throw new Error('Malformed base64 payload');
}
content = buf.toString('utf-8');
} catch (decodeErr) {
throw new Error(
`Invalid base64 content for ${logicalPath}: ${decodeErr}`
);
}🤖 Prompt for AI Agents
In doc-agents/src/agent/doc_processing/docs-orchestrator.ts around lines 86 to
97, the round-trip base64 validation is asymmetric because it only strips
whitespace from the original base64Content; normalize both sides before
comparing to avoid false positives/negatives. Fix by creating a normalized input
string (remove all whitespace) and a normalized output string (re-encode the
decoded buffer to base64 and remove whitespace from that result) and compare
those two normalized values; if they differ throw the malformed payload error as
before. Ensure you still decode to utf-8 for content after the validation
succeeds.
| await removeVectorsByPath(ctx, logicalPath, VECTOR_STORE_NAME); | ||
|
|
||
| // Process the document content into chunks | ||
| const chunks = await processDoc(content); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🧩 Analysis chain
🏁 Script executed:
#!/bin/bash
# Find and examine processDoc implementation
rg -n "export.*function.*processDoc" --type=ts -A 10
# Also check the file structure
git ls-files "doc-agents/**/*orchestrator*" --type=tsRepository: agentuity/docs
Length of output: 4038
🏁 Script executed:
#!/bin/bash
# Get the full context around line 103 in the orchestrator file
cat -n "doc-agents/src/agent/doc_processing/docs-orchestrator.ts" | sed -n '95,115p'Repository: agentuity/docs
Length of output: 775
🏁 Script executed:
#!/bin/bash
# Search for how chunks variable is used after line 103
rg -n "chunks" "doc-agents/src/agent/doc_processing/docs-orchestrator.ts" -A 2 -B 2Repository: agentuity/docs
Length of output: 874
🏁 Script executed:
#!/bin/bash
# Check chunkAndEnrichDoc implementation
rg -n "export.*function.*chunkAndEnrichDoc|function.*chunkAndEnrichDoc" --type=ts -A 15Repository: agentuity/docs
Length of output: 2966
🏁 Script executed:
#!/bin/bash
# Check createVectorEmbedding more closely
rg -n "async function createVectorEmbedding" --type=ts -A 20Repository: agentuity/docs
Length of output: 3695
🏁 Script executed:
#!/bin/bash
# Look for tests related to empty content or empty chunks
rg -n "empty|processDoc.*\[\]|chunks.*=.*\[\]" "doc-agents/src/agent/doc_processing/" --type=ts -B 2 -A 2Repository: agentuity/docs
Length of output: 911
Consider adding explicit guard for empty chunks before upserting.
The code does not explicitly handle when processDoc returns an empty array. While the spread operator safely handles zero items, calling ctx.vector.upsert() with no chunks may not reflect intended behavior. Either add a guard like:
if (chunksWithMetadata.length > 0) {
await ctx.vector.upsert(VECTOR_STORE_NAME, ...chunksWithMetadata);
}Or verify that your vector store handles empty upserts as a no-op and document this assumption.
🤖 Prompt for AI Agents
In doc-agents/src/agent/doc_processing/docs-orchestrator.ts around line 103,
processDoc may return an empty array but the code proceeds to upsert without an
explicit guard; add a simple length check so you only call
ctx.vector.upsert(VECTOR_STORE_NAME, ...) when chunksWithMetadata.length > 0 (or
alternatively assert/document that the vector store treats empty upserts as a
no-op) to avoid unintended behavior or unnecessary calls.
| export async function clearVectorDb(ctx: any) { | ||
| ctx.logger.info('Clearing all vectors from store: %s', VECTOR_STORE_NAME); | ||
| while (true) { | ||
| const batch = await ctx.vector.search(VECTOR_STORE_NAME, { | ||
| query: ' ', | ||
| limit: 1000, | ||
| }); | ||
| if (batch.length === 0) break; | ||
|
|
||
| // Batch delete all vectors at once for efficiency | ||
| const keys = batch.map((v: { key: string }) => v.key); | ||
| await ctx.vector.delete(VECTOR_STORE_NAME, ...keys); | ||
| } | ||
| } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Add error handling and consider a safety confirmation.
This function has two concerns:
-
Missing error handling: Similar to
removeVectorsByPath, the loop lacks error handling for vector operations, which could leave the operation incomplete. -
No safety confirmation: This is a destructive operation that clears the entire vector database. Consider adding a parameter or check to confirm the operation is intentional, especially if this could be called accidentally.
🔎 Proposed improvements
-export async function clearVectorDb(ctx: any) {
+export async function clearVectorDb(ctx: any, confirm: boolean = false) {
+ if (!confirm) {
+ ctx.logger.warn('clearVectorDb called without confirmation - skipping');
+ return;
+ }
+
ctx.logger.info('Clearing all vectors from store: %s', VECTOR_STORE_NAME);
while (true) {
- const batch = await ctx.vector.search(VECTOR_STORE_NAME, {
- query: ' ',
- limit: 1000,
- });
+ let batch;
+ try {
+ batch = await ctx.vector.search(VECTOR_STORE_NAME, {
+ query: ' ',
+ limit: 1000,
+ });
+ } catch (searchErr) {
+ ctx.logger.error('Error searching vectors during clear: %o', searchErr);
+ throw searchErr;
+ }
+
if (batch.length === 0) break;
// Batch delete all vectors at once for efficiency
const keys = batch.map((v: { key: string }) => v.key);
- await ctx.vector.delete(VECTOR_STORE_NAME, ...keys);
+ try {
+ await ctx.vector.delete(VECTOR_STORE_NAME, ...keys);
+ } catch (deleteErr) {
+ ctx.logger.error('Error deleting vectors during clear: %o', deleteErr);
+ throw deleteErr;
+ }
}
+ ctx.logger.info('Successfully cleared all vectors from store: %s', VECTOR_STORE_NAME);
}📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| export async function clearVectorDb(ctx: any) { | |
| ctx.logger.info('Clearing all vectors from store: %s', VECTOR_STORE_NAME); | |
| while (true) { | |
| const batch = await ctx.vector.search(VECTOR_STORE_NAME, { | |
| query: ' ', | |
| limit: 1000, | |
| }); | |
| if (batch.length === 0) break; | |
| // Batch delete all vectors at once for efficiency | |
| const keys = batch.map((v: { key: string }) => v.key); | |
| await ctx.vector.delete(VECTOR_STORE_NAME, ...keys); | |
| } | |
| } | |
| export async function clearVectorDb(ctx: any, confirm: boolean = false) { | |
| if (!confirm) { | |
| ctx.logger.warn('clearVectorDb called without confirmation - skipping'); | |
| return; | |
| } | |
| ctx.logger.info('Clearing all vectors from store: %s', VECTOR_STORE_NAME); | |
| while (true) { | |
| let batch; | |
| try { | |
| batch = await ctx.vector.search(VECTOR_STORE_NAME, { | |
| query: ' ', | |
| limit: 1000, | |
| }); | |
| } catch (searchErr) { | |
| ctx.logger.error('Error searching vectors during clear: %o', searchErr); | |
| throw searchErr; | |
| } | |
| if (batch.length === 0) break; | |
| // Batch delete all vectors at once for efficiency | |
| const keys = batch.map((v: { key: string }) => v.key); | |
| try { | |
| await ctx.vector.delete(VECTOR_STORE_NAME, ...keys); | |
| } catch (deleteErr) { | |
| ctx.logger.error('Error deleting vectors during clear: %o', deleteErr); | |
| throw deleteErr; | |
| } | |
| } | |
| ctx.logger.info('Successfully cleared all vectors from store: %s', VECTOR_STORE_NAME); | |
| } |
🤖 Prompt for AI Agents
In doc-agents/src/agent/doc_processing/docs-orchestrator.ts around lines 144 to
157, the clearVectorDb function needs error handling and a safety confirmation:
wrap the vector search/delete loop in try/catch (log the error with
ctx.logger.error and rethrow or return a failure) and handle transient failures
(optionally retry or break on repeated errors) so the loop cannot silently leave
the DB in a partial state; add an explicit confirmation parameter (e.g.,
requireConfirm boolean or a required confirmation token) and check it at the
start, logging and throwing if not provided to prevent accidental full clears;
ensure deletes are still batched but guarded by the confirmation and error
handling.
- Implemented a new Documentation Q&A agent that answers questions about Agentuity documentation using Retrieval-Augmented Generation (RAG). - Created supporting files including agent logic, prompt handling, document retrieval, and type definitions. - Added API route for the agent to handle requests and return structured responses. - Updated the frontend to interact with the new agent, allowing users to ask questions about documentation directly.
- Removed the 'hello' agent and its associated files from the project. - Updated API routes to remove references to the 'hello' agent. - Introduced a new middleware for bearer token authentication to enhance security for API routes. - Updated TypeScript configuration to include paths for middleware.
- Changed agentBaseUrl to use a local development URL for easier testing. - Refactored buildAgentConfig to accept an endpoint instead of an agent ID. - Updated getAgentQaConfig and getAgentPulseConfig to use specific API endpoints. - Improved error messages for agent configuration validation.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 5
🧹 Nitpick comments (11)
lib/env.ts (3)
4-9: Move import statement to the top of the file.The import statement on line 9 follows the interface declaration. Standard practice is to place all imports at the top of the file before any declarations.
🔎 Proposed fix
+import { config } from '@/lib/config'; + /** * Environment variable validation and configuration utility */ export interface AgentConfig { url: string; bearerToken?: string; } - -import { config } from '@/lib/config';
24-27: Consider normalizing URL construction to handle trailing slashes.If
AGENT_BASE_URLis set with a trailing slash (e.g.,http://example.com/), the resulting URL will have double slashes (http://example.com//api/doc-qa). While most servers handle this gracefully, it's cleaner to normalize.🔎 Proposed fix
return { - url: `${baseUrl}${endpoint}`, + url: `${baseUrl.replace(/\/+$/, '')}${endpoint}`, bearerToken: bearerToken || undefined, };
59-64: Type augmentation won't affectprocess.envtyping.The
ProcessEnvinterface declared in the global scope doesn't augmentNodeJS.ProcessEnv, so TypeScript won't recognize these properties onprocess.env.🔎 Proposed fix
declare global { - interface ProcessEnv { - AGENT_BASE_URL?: string; - AGENT_BEARER_TOKEN?: string; + namespace NodeJS { + interface ProcessEnv { + AGENT_BASE_URL?: string; + AGENT_BEARER_TOKEN?: string; + } } }doc-agents/src/api/doc-qa/route.ts (1)
7-12: Consider adding explicit error handling for robustness.While the agent's
answerQuestionfunction has internal error handling (as shown in rag.ts), adding a try-catch block arounddocQAAgent.run(data)would improve robustness by handling unexpected errors at the route level and providing consistent error responses to clients.🔎 Proposed error handling enhancement
router.post('/', bearerTokenAuth, docQAAgent.validator(), async (c) => { - const data = c.req.valid('json'); - const result = await docQAAgent.run(data); - return c.json(result); + try { + const data = c.req.valid('json'); + const result = await docQAAgent.run(data); + return c.json(result); + } catch (error) { + c.var.logger.error('Error in doc-qa route:', error); + return c.json({ error: 'Failed to process question' }, 500); + } });doc-agents/src/web/App.tsx (4)
84-86: Consider using document content as key.Using array index as the key can cause React reconciliation issues if the documents array is reordered. While unlikely in this case, it's better practice to use a stable identifier.
🔎 Proposed fix
- {result.documents.map((doc, idx) => ( - <li key={idx}>{doc}</li> + {result.documents.map((doc) => ( + <li key={doc}>{doc}</li> ))}
162-162: Use self-closing SVG element.The
<path>element should be self-closing since it has no children, improving code consistency and following JSX best practices.🔎 Proposed fix
- <path d="M20 6 9 17l-5-5"></path> + <path d="M20 6 9 17l-5-5" />
145-147: Consider adding a type guard to avoid non-null assertions.The
filter(Boolean)removes null values but TypeScript doesn't automatically narrow the type. Using a type guard would eliminate the need for non-null assertions (step!).🔎 Proposed fix
] - .filter(Boolean) - .map((step) => ( - <div key={step!.key} className="step"> + .filter((step): step is NonNullable<typeof step> => step !== null) + .map((step) => ( + <div key={step.key} className="step"> <div className="step-icon">
176-448: Consider extracting styles to a separate CSS file.The large inline style block (270+ lines) makes the component harder to maintain and increases bundle size. Moving styles to a separate CSS file or using a CSS-in-JS solution would improve maintainability and enable better caching.
doc-agents/src/agent/doc_qa/types.ts (1)
24-44: Consider generating types from schemas to reduce duplication.The TypeScript types (lines 25-44) manually duplicate the schema definitions (lines 3-22). Many schema libraries support generating TypeScript types from schemas, which would maintain a single source of truth.
doc-agents/src/agent/doc_qa/retriever.ts (1)
167-167: Consider adding type definition for vector result.The cast to
anyto access thesimilarityproperty indicates missing type information. Consider defining a proper type for the vector search result to improve type safety.doc-agents/src/agent/doc_qa/rag.ts (1)
102-109: Consider clarifying the prompt parameter.The
promptparameter on line 106 provides general guidance that could be incorporated into the system prompt. Consider either making this more specific to the current query or removing it if the system prompt is sufficient.
📜 Review details
Configuration used: Organization UI
Review profile: CHILL
Plan: Pro
⛔ Files ignored due to path filters (3)
doc-agents/src/generated/app.tsis excluded by!**/generated/**doc-agents/src/generated/registry.tsis excluded by!**/generated/**doc-agents/src/generated/routes.tsis excluded by!**/generated/**
📒 Files selected for processing (13)
doc-agents/src/agent/doc_qa/agent.tsdoc-agents/src/agent/doc_qa/index.tsdoc-agents/src/agent/doc_qa/prompt.tsdoc-agents/src/agent/doc_qa/rag.tsdoc-agents/src/agent/doc_qa/retriever.tsdoc-agents/src/agent/doc_qa/types.tsdoc-agents/src/api/doc-qa/route.tsdoc-agents/src/api/index.tsdoc-agents/src/middleware/auth.tsdoc-agents/src/web/App.tsxdoc-agents/tsconfig.jsonlib/config.tslib/env.ts
🚧 Files skipped from review as they are similar to previous changes (1)
- doc-agents/tsconfig.json
🧰 Additional context used
🧬 Code graph analysis (4)
doc-agents/src/api/doc-qa/route.ts (1)
doc-agents/src/middleware/auth.ts (1)
bearerTokenAuth(7-33)
doc-agents/src/agent/doc_qa/agent.ts (1)
doc-agents/src/agent/doc_qa/rag.ts (1)
answerQuestion(14-130)
doc-agents/src/agent/doc_qa/retriever.ts (1)
doc-agents/src/agent/doc_qa/types.ts (1)
RelevantDoc(25-31)
doc-agents/src/agent/doc_qa/prompt.ts (1)
doc-agents/src/agent/doc_qa/types.ts (1)
PromptType(38-38)
🪛 Biome (2.1.2)
doc-agents/src/web/App.tsx
[error] 162-162: JSX elements without children should be marked as self-closing. In JSX, it is valid for any element to be self-closing.
Safe fix: Use a self-closing element instead.
(lint/style/useSelfClosingElements)
[error] 85-85: Avoid using the index of an array as key property in an element.
This is the source of the key value.
The order of the items may change, and this also affects performances and component state.
Check the React documentation.
(lint/suspicious/noArrayIndexKey)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (1)
- GitHub Check: sync
🔇 Additional comments (15)
lib/config.ts (1)
9-10: LGTM!The shift to an endpoint-based URL construction approach is clear, and the localhost default is appropriate for local development. The comment adds helpful context.
lib/env.ts (2)
30-36: LGTM!Clean wrapper functions with clear, fixed endpoint paths.
41-52: LGTM!The validation logic and error messaging are clear and helpful. Since both agent configs share the same base URL validation via
buildAgentConfig, validating one effectively validates the shared configuration.doc-agents/src/agent/doc_qa/index.ts (1)
1-1: LGTM! Clean barrel export pattern.This is a standard and idiomatic TypeScript re-export pattern that provides a clean public API surface for the DocQA agent module.
doc-agents/src/agent/doc_qa/agent.ts (1)
5-20: LGTM! Well-structured agent definition.The agent is properly configured with:
- Clear input/output schemas matching the RAG implementation
- Appropriate delegation to the
answerQuestionfunction- Consistent error handling inherited from the RAG layer
doc-agents/src/middleware/auth.ts (1)
7-33: Good security practices observed.The middleware correctly:
- Validates Authorization header presence and format
- Fails closed when
AGENT_BEARER_TOKENis not configured- Logs authentication failures without exposing sensitive data
- Returns consistent error messages that don't leak implementation details
doc-agents/src/web/App.tsx (2)
1-5: LGTM!The imports and environment variable setup are correct and follow best practices for React 19.
6-9: LGTM!The component setup uses React 19 hooks correctly and follows modern patterns.
doc-agents/src/agent/doc_qa/types.ts (1)
1-23: LGTM!The schema definitions are well-structured and properly typed. The use of
@agentuity/schemawith optional fields and enums follows best practices.doc-agents/src/agent/doc_qa/prompt.ts (2)
1-12: LGTM!The imports and Zod schema definition are clean and properly structured for AI SDK compatibility.
14-77: LGTM!The rephrasing logic is well-implemented with appropriate error handling, conservative prompting, and safe fallback behavior. The low temperature (0.1) ensures consistent results.
doc-agents/src/agent/doc_qa/rag.ts (4)
1-12: LGTM!The imports and Zod schema are properly structured and match the corresponding TypeScript types.
14-22: LGTM!The function properly chains prompt rephrasing and document retrieval, creating a logical workflow.
24-100: LGTM!The system prompt is comprehensive and well-structured, with clear rules, MDX formatting examples, and navigation conventions. The guidance for document citation with heading anchors is particularly well-documented.
110-129: LGTM!The error handling is robust with a user-friendly MDX-formatted fallback response. The logging ensures debugging visibility.
| /** | ||
| * Determines the prompt type based on the input string using LLM classification. | ||
| * Uses specific, measurable criteria to decide between Normal and Agentic RAG. | ||
| * @param ctx - Agent Context for logging and LLM access | ||
| * @param input - The input string to analyze | ||
| * @returns {Promise<PromptType>} - The determined PromptType | ||
| */ |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Update JSDoc to match implementation.
The JSDoc mentions "Agentic RAG" but the actual return type is PromptType which uses the enum values "Normal" and "Thinking". Update the documentation to use consistent terminology.
🔎 Proposed fix
/**
* Determines the prompt type based on the input string using LLM classification.
- * Uses specific, measurable criteria to decide between Normal and Agentic RAG.
+ * Uses specific, measurable criteria to decide between Normal and Thinking prompt types.
* @param ctx - Agent Context for logging and LLM access
* @param input - The input string to analyze
* @returns {Promise<PromptType>} - The determined PromptType
*/📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| /** | |
| * Determines the prompt type based on the input string using LLM classification. | |
| * Uses specific, measurable criteria to decide between Normal and Agentic RAG. | |
| * @param ctx - Agent Context for logging and LLM access | |
| * @param input - The input string to analyze | |
| * @returns {Promise<PromptType>} - The determined PromptType | |
| */ | |
| /** | |
| * Determines the prompt type based on the input string using LLM classification. | |
| * Uses specific, measurable criteria to decide between Normal and Thinking prompt types. | |
| * @param ctx - Agent Context for logging and LLM access | |
| * @param input - The input string to analyze | |
| * @returns {Promise<PromptType>} - The determined PromptType | |
| */ |
🤖 Prompt for AI Agents
In doc-agents/src/agent/doc_qa/prompt.ts around lines 79 to 85, the JSDoc
references "Agentic RAG" but the function actually returns PromptType enum
values "Normal" and "Thinking"; update the JSDoc to use the same terminology as
the implementation (mention PromptType and the enum values "Normal" and
"Thinking"), adjust the description to say it decides between Normal and
Thinking prompt types based on LLM classification, and ensure @returns documents
{Promise<PromptType>} with the correct enum value descriptions.
| // Query for all chunks at once | ||
| const chunkQueries = validIndices.map((index) => | ||
| ctx.vector.search(VECTOR_STORE_NAME, { | ||
| query: path, | ||
| limit: 1, | ||
| metadata: { path: path, chunkIndex: index }, | ||
| }) | ||
| ); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🧩 Analysis chain
🏁 Script executed:
#!/bin/bash
# First, locate and read the target file
find . -name "retriever.ts" -path "*/doc_qa/*" -type fRepository: agentuity/docs
Length of output: 100
🏁 Script executed:
#!/bin/bash
# Check how vector.search is used elsewhere in the codebase
rg -n -C3 'vector\.search\(' --type=tsRepository: agentuity/docs
Length of output: 4692
🏁 Script executed:
#!/bin/bash
# Also search for vector store initialization and type definitions
rg -n 'vector\s*[:=]' --type=ts -A2 | head -100Repository: agentuity/docs
Length of output: 40
🏁 Script executed:
#!/bin/bash
# Read the retriever.ts file context
sed -n '1,60p' doc-agents/src/agent/doc_qa/retriever.tsRepository: agentuity/docs
Length of output: 1668
🏁 Script executed:
#!/bin/bash
# Check the corresponding file in agent-docs to see the difference
sed -n '1,60p' agent-docs/src/agents/doc-qa/retriever.tsRepository: agentuity/docs
Length of output: 1662
Change query: path to empty/whitespace query.
Line 51 uses the file path as the semantic search query, but should use an empty string or whitespace like the corresponding implementation in agent-docs/src/agents/doc-qa/retriever.ts (line 52 uses query: ' '). Since you're filtering by metadata (path and chunkIndex), the query parameter should be an empty/neutral value to retrieve chunks by metadata only, not by semantic similarity to the file path string.
query: ' ',
🤖 Prompt for AI Agents
In doc-agents/src/agent/doc_qa/retriever.ts around lines 48 to 55, the
vector.search call uses query: path which causes semantic search on the file
path; change the query to an empty/neutral string (e.g., a single space ' ' or
empty string '') so the search is driven only by the metadata filter (path and
chunkIndex), leaving the rest of the call intact.
| import { createRouter } from '@agentuity/runtime'; | ||
|
|
||
| const api = createRouter(); | ||
|
|
||
| export default api; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🧩 Analysis chain
🏁 Script executed:
#!/bin/bash
# Description: Search for route mounting patterns and verify API router usage
# Search for .route() calls that mount sub-routers
echo "=== Searching for route mounting patterns ==="
rg -n "\.route\(" --type=ts -A 2 -B 2
# Search for imports of this api router to see where it's used
echo -e "\n=== Searching for api router imports ==="
rg -n "from ['\"].*api['\"]" --type=ts -A 2 -B 2
# Search for doc-qa and process-docs route imports
echo -e "\n=== Searching for doc-qa and process-docs route references ==="
rg -n "(doc-qa|process-docs)" --type=ts -A 2 -B 2Repository: agentuity/docs
Length of output: 8468
🏁 Script executed:
#!/bin/bash
# Check the structure of the api directory
echo "=== API directory structure ==="
find doc-agents/src/api -type f -name "*.ts" | head -20
# Check if doc-agents/src/api/index.ts is imported or exported anywhere
echo -e "\n=== Checking imports/exports of api/index.ts ==="
rg -n "from ['\"].*api['\"]|from ['\"].*api/index" --type=ts
# Check if api/index.ts is referenced in app.ts or main entry points
echo -e "\n=== Checking app.ts structure around route mounting ==="
sed -n '200,220p' doc-agents/src/generated/app.ts
# Check if there are other routers defined in the api directory
echo -e "\n=== Checking for router definitions in api directory ==="
rg -n "createRouter\(\)" doc-agents/src/api --type=ts -B 1 -A 3Repository: agentuity/docs
Length of output: 2344
This file is unused and should likely be removed.
The router is created but never imported or used anywhere in the codebase. Routes for /doc-qa and /process-docs are successfully mounted directly in doc-agents/src/generated/app.ts from their individual sub-routers (doc-qa/route.ts and process-docs/index.ts), completely bypassing this file. Either remove index.ts if it's not part of the intended architecture, or clarify its purpose if it's meant to aggregate sub-routers in the future.
🤖 Prompt for AI Agents
In doc-agents/src/api/index.ts lines 1-5, the file creates a router that is
never imported or used anywhere; remove this unused file to eliminate dead code
(delete doc-agents/src/api/index.ts) or, if intended to aggregate sub-routers,
modify the project to export and use this router by importing and mounting the
sub-routers (e.g., export the router and ensure generated/app.ts imports and
mounts it) — choose one: delete the file if unused, or implement and wire it
into the app as the central router.
| const token = authHeader.slice(7); | ||
|
|
||
| // Validate token matches expected value | ||
| if (!expectedToken || token !== expectedToken) { | ||
| c.var.logger.warn('Invalid bearer token'); | ||
| return c.json({ error: 'Invalid bearer token' }, 401); | ||
| } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Critical: Use constant-time comparison to prevent timing attacks.
Line 26 uses !== to compare the bearer token, which is vulnerable to timing attacks. An attacker could measure response times to guess the token byte-by-byte. Use crypto.timingSafeEqual() for secure, constant-time string comparison.
🔎 Proposed fix using constant-time comparison
import { createMiddleware } from 'hono/factory';
+import { timingSafeEqual } from 'crypto';
/**
* Bearer token authentication middleware
* Validates the Authorization header contains the correct bearer token
*/
export const bearerTokenAuth = createMiddleware(async (c, next) => {
const authHeader = c.req.header('Authorization');
const expectedToken = process.env.AGENT_BEARER_TOKEN;
// Check if Authorization header exists
if (!authHeader) {
c.var.logger.warn('Missing Authorization header');
return c.json({ error: 'Missing Authorization header' }, 401);
}
// Check if it starts with Bearer
if (!authHeader.startsWith('Bearer ')) {
c.var.logger.warn('Invalid Authorization header format');
return c.json({ error: 'Invalid Authorization header format' }, 401);
}
const token = authHeader.slice(7);
// Validate token matches expected value
- if (!expectedToken || token !== expectedToken) {
+ if (!expectedToken) {
+ c.var.logger.error('AGENT_BEARER_TOKEN not configured');
+ return c.json({ error: 'Invalid bearer token' }, 401);
+ }
+
+ // Use constant-time comparison to prevent timing attacks
+ const tokenBuffer = Buffer.from(token);
+ const expectedBuffer = Buffer.from(expectedToken);
+
+ if (tokenBuffer.length !== expectedBuffer.length || !timingSafeEqual(tokenBuffer, expectedBuffer)) {
c.var.logger.warn('Invalid bearer token');
return c.json({ error: 'Invalid bearer token' }, 401);
}
// Token is valid, proceed to next handler
await next();
});📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| const token = authHeader.slice(7); | |
| // Validate token matches expected value | |
| if (!expectedToken || token !== expectedToken) { | |
| c.var.logger.warn('Invalid bearer token'); | |
| return c.json({ error: 'Invalid bearer token' }, 401); | |
| } | |
| import { createMiddleware } from 'hono/factory'; | |
| import { timingSafeEqual } from 'crypto'; | |
| /** | |
| * Bearer token authentication middleware | |
| * Validates the Authorization header contains the correct bearer token | |
| */ | |
| export const bearerTokenAuth = createMiddleware(async (c, next) => { | |
| const authHeader = c.req.header('Authorization'); | |
| const expectedToken = process.env.AGENT_BEARER_TOKEN; | |
| // Check if Authorization header exists | |
| if (!authHeader) { | |
| c.var.logger.warn('Missing Authorization header'); | |
| return c.json({ error: 'Missing Authorization header' }, 401); | |
| } | |
| // Check if it starts with Bearer | |
| if (!authHeader.startsWith('Bearer ')) { | |
| c.var.logger.warn('Invalid Authorization header format'); | |
| return c.json({ error: 'Invalid Authorization header format' }, 401); | |
| } | |
| const token = authHeader.slice(7); | |
| // Validate token matches expected value | |
| if (!expectedToken) { | |
| c.var.logger.error('AGENT_BEARER_TOKEN not configured'); | |
| return c.json({ error: 'Invalid bearer token' }, 401); | |
| } | |
| // Use constant-time comparison to prevent timing attacks | |
| const tokenBuffer = Buffer.from(token); | |
| const expectedBuffer = Buffer.from(expectedToken); | |
| if (tokenBuffer.length !== expectedBuffer.length || !timingSafeEqual(tokenBuffer, expectedBuffer)) { | |
| c.var.logger.warn('Invalid bearer token'); | |
| return c.json({ error: 'Invalid bearer token' }, 401); | |
| } | |
| // Token is valid, proceed to next handler | |
| await next(); | |
| }); |
🤖 Prompt for AI Agents
In doc-agents/src/middleware/auth.ts around lines 23 to 29, the token comparison
uses !== which is vulnerable to timing attacks; replace the direct equality
check with a constant-time comparison using Node's crypto.timingSafeEqual:
import crypto, ensure expectedToken exists, then compare in constant time by
converting both values to Buffers of equal length (either use
crypto.timingSafeEqual directly when buffers are same length or hash both inputs
to a fixed length like SHA-256 and compare those hashes) and use that result to
decide logging/response; keep the existing warning and 401 response path.
| <svg | ||
| aria-hidden="true" | ||
| aria-label="Agentuity Logo" | ||
| className="logo" | ||
| fill="none" | ||
| height="191" | ||
| viewBox="0 0 220 191" | ||
| width="220" | ||
| xmlns="http://www.w3.org/2000/svg" | ||
| > |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Remove aria-hidden="true" to fix accessibility.
The SVG has both aria-hidden="true" and aria-label="Agentuity Logo", which is contradictory. The aria-hidden attribute prevents screen readers from announcing the element, making the aria-label ineffective.
🔎 Proposed fix
<svg
- aria-hidden="true"
aria-label="Agentuity Logo"
+ role="img"
className="logo"
fill="none"
height="191"
viewBox="0 0 220 191"
width="220"
xmlns="http://www.w3.org/2000/svg"
>📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| <svg | |
| aria-hidden="true" | |
| aria-label="Agentuity Logo" | |
| className="logo" | |
| fill="none" | |
| height="191" | |
| viewBox="0 0 220 191" | |
| width="220" | |
| xmlns="http://www.w3.org/2000/svg" | |
| > | |
| <svg | |
| aria-label="Agentuity Logo" | |
| role="img" | |
| className="logo" | |
| fill="none" | |
| height="191" | |
| viewBox="0 0 220 191" | |
| width="220" | |
| xmlns="http://www.w3.org/2000/svg" | |
| > |
🤖 Prompt for AI Agents
In doc-agents/src/web/App.tsx around lines 14 to 23, the SVG is marked with both
aria-hidden="true" and aria-label="Agentuity Logo" which is contradictory;
remove the aria-hidden="true" attribute so the aria-label can be announced by
assistive technologies (optionally ensure a role="img" is present if you want to
explicitly expose it as an image).
- Replaced instances of `agentuity` with `bunx @agentuity/cli` in various skill documentation files to standardize command execution. - Updated the README to reflect the new total skills count and generation date. - Removed the `agentuity-cli-upgrade` skill from the documentation as it is no longer applicable.
- Replaced environment variable validation with direct API service calls for agent configuration. - Updated API routes to utilize new service methods for querying agents and managing tutorial states. - Refactored session management to improve error handling and streamline KV store interactions. - Introduced a new title generation service for session titles based on conversation history. - Removed deprecated environment validation logic and associated files to simplify the codebase.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 20
Note
Due to the large number of review comments, Critical, Major severity comments were prioritized as inline comments.
🤖 Fix all issues with AI Agents
In @app/api/sessions/[sessionId]/messages/route.ts:
- Around line 166-182: The async onTutorialData callback currently performs
await TutorialStateManager.updateTutorialProgress but may be invoked without
awaiting by callAgentPulseStreaming; wrap the body of onTutorialData in a
try-catch that catches and logs errors (including the thrown error) and ensure
callAgentPulseStreaming awaits the callback if it supports async handlers (or
otherwise handle returned Promise), referencing onTutorialData,
TutorialStateManager.updateTutorialProgress, callAgentPulseStreaming,
controller.enqueue and encoder.encode so failures in updateTutorialProgress are
caught and do not become unhandled rejections.
- Line 16: Remove the unused constant AGENT_REQUEST_TIMEOUT from this file:
locate the declaration const AGENT_REQUEST_TIMEOUT = 30000; and delete it (and
any related comments) since timeouts are handled by callAgentPulseStreaming;
ensure there are no other references to AGENT_REQUEST_TIMEOUT in this module
after removal.
In @doc-agents/.agents/skills/agentuity-cli-auth-ssh-add/SKILL.md:
- Around line 28-38: The options table incorrectly marks `--file` as required
while examples for "Add SSH key interactively" and "Add SSH key from stdin" omit
it; update SKILL.md so the table marks `--file` as optional (change "Yes" to
"No" or "Optional") and add a short note in the table or header that the command
reads from stdin when `--file` is not provided, or alternatively update the
examples to always include `--file` and show the stdin/interactive variants
explicitly (modify the "Add SSH key interactively" and "Add SSH key from stdin"
examples to either include `--file <path>` or annotate that stdin/interactive
mode is used).
In @doc-agents/.agents/skills/agentuity-cli-cloud-agent-get/SKILL.md:
- Around line 50-77: The generated SKILL.md contains placeholder types
("unknown") for fields `description`, `deploymentId`, and `metadata` (e.g., in
agentuity-cli-cloud-agent-get SKILL.md); update the upstream Agentuity CLI
schema generator to map these schema properties to their real types (e.g.,
string/object/UUID/etc.) instead of emitting "unknown": locate the generator
logic that builds property type strings (the module invoked by the CLI command
`agentuity ai skills generate`) and add explicit handlers for `description`,
`deploymentId`, and `metadata` (or a generic rule that resolves unknown JSON
Schema/$ref types properly), then run the generator to regenerate all affected
SKILL.md files (cloud-deployment-show, cloud-keyvalue-get, cloud-session-get,
cloud-thread-get, profile-show, project-show) so the docs reflect correct types.
- Line 35: Update the example description that currently reads "Get item
details:" to accurately reflect the command it documents by changing the text to
"Get agent details:" (or similar agent-specific phrasing); locate the occurrence
of the string "Get item details:" in SKILL.md and replace it so the example
description matches the agent details retrieval command.
- Around line 29-31: Replace the placeholder "-" description for the
`<agent_id>` argument in SKILL.md with a concise explanation: state that
`<agent_id>` is the unique identifier (UUID or slug) of the agent to retrieve,
explain where to get it (e.g., from the Agents list in the web UI, the agent
details page, or from the CLI/API list endpoints), and give an example format
(e.g., "e.g., 123e4567-e89b-12d3-a456-426614174000" or "agent-slug"). Ensure the
Description cell for `<agent_id>` clearly instructs users how to locate or
derive the ID before calling the skill.
In @doc-agents/.agents/skills/agentuity-cli-cloud-db-sql/SKILL.md:
- Around line 35-53: Examples 2 and 3 use the wrong subcommands ("cloud db exec"
and "cloud db query") and should match the documented canonical command
"agentuity cloud db sql"; update the example lines that currently show "bunx
@agentuity/cli cloud db exec my-database ..." and "bunx @agentuity/cli cloud db
query my-database ..." to use "bunx @agentuity/cli cloud db sql my-database ..."
(including the --json flag where present) so all examples consistently use the
`sql` subcommand, or alternatively add a note clarifying that `exec` and `query`
are aliases of `sql` if that is intended.
In @doc-agents/.agents/skills/agentuity-cli-cloud-deploy/SKILL.md:
- Around line 16-20: Remove the duplicate/malformed prerequisite entry "- auth
login" from the Prerequisites list in SKILL.md (the block containing
"Authenticated with `agentuity auth login`" and "Project context required...");
keep the existing "Authenticated with `agentuity auth login`" line intact and
delete the stray "- auth login" line so the prerequisites are not duplicated or
corrupted.
In @doc-agents/.agents/skills/agentuity-cli-cloud-deployment-rollback/SKILL.md:
- Around line 16-20: The "cloud deploy" line in the Prerequisites is ambiguous;
update the Prerequisites section under "## Prerequisites" to explicitly state
what is required (e.g., whether it refers to an Agentuity skill named
"cloud-deploy", a CLI command `agentuity cloud deploy`, or a configured cloud
deployment service) and provide the exact install/configure step or command to
satisfy it (for example: "Install the cloud-deploy skill: `agentuity skill
install cloud-deploy`" or "Ensure Cloud Deploy is configured in your project:
add X config Y"). Include the clarified phrasing in place of the bare "cloud
deploy" text so readers know the exact dependency and how to fulfill it.
In @doc-agents/.agents/skills/agentuity-cli-cloud-env-delete/SKILL.md:
- Around line 24-46: The examples in SKILL.md use a different CLI invocation
than the documented usage; update the example commands to match the documented
pattern (use "agentuity cloud env delete <key>" and "agentuity cloud env rm
<key>" instead of "bunx @agentuity/cli ..."), and replace the two identical
"Delete item:" captions with specific descriptions—e.g., "Delete using full
command:" for the delete example and "Delete using the rm alias:" for the rm
example—so the examples align with the usage shown by the "agentuity cloud env
delete" heading.
- Around line 28-32: Update the empty description for the `<key>` argument in
the Arguments table: replace the placeholder dash with a clear description such
as "Name of the environment variable to delete" (or "Key of the environment
variable to delete") so the `<key>` field in the skill SKILL.md explicitly
documents that it is the environment variable name to remove.
In @doc-agents/.agents/skills/agentuity-cli-cloud-keyvalue-delete/SKILL.md:
- Around line 28-33: Update the arguments table in SKILL.md to add clear
descriptions for `<namespace>` and `<key>`: explain that `<namespace>` is the
logical grouping or bucket for stored key-value pairs (list common namespaces or
how to query available namespaces, e.g., "defaults, user, session") and state
any format constraints (allowed characters, max length), and describe `<key>` as
the identifier within that namespace used to locate the value (mention format
expectations, uniqueness within a namespace, and any encoding rules). Ensure
both descriptions are brief and actionable so users know what values are valid
and how to discover available namespaces and keys.
- Around line 35-53: The examples show shorthand aliases but the Usage section
documents the full command 'agentuity cloud keyvalue delete'; update SKILL.md so
they match by either adding the official aliases ('kv delete' and 'kv rm') to
the Usage/Commands list and noting they map to 'agentuity cloud keyvalue
delete', or replace the example invocations with the primary form 'bunx
@agentuity/cli agentuity cloud keyvalue delete <env> <key>' (and add alias
examples only if they are official). Reference the command symbols 'agentuity
cloud keyvalue delete', 'kv delete', and 'kv rm' when editing the Usage and
Examples to ensure clarity.
In @doc-agents/.agents/skills/agentuity-cli-cloud-keyvalue-keys/SKILL.md:
- Around line 24-52: The examples for the keys skill inconsistently label
aliases: the Usage shows "agentuity cloud keyvalue keys", Examples use the
package-runner "bunx @agentuity/cli kv", and only "kv ls" is marked "(using
alias)" while "kv list" is not; update the SKILL.md examples so aliases are
documented consistently—either mark both "kv ls" and "kv list" as aliases (e.g.,
“(alias)”) or remove the “(using alias)” note entirely from the examples for
production/cache/staging so they match the pattern used across other keyvalue
skills.
In @doc-agents/.agents/skills/agentuity-cli-cloud-secret-pull/SKILL.md:
- Around line 24-25: The examples in SKILL.md are inconsistent with the usage
line: change the example invocations (currently using "bunx @agentuity/cli
secret pull") to match the documented command "agentuity cloud secret pull
[options]" or add a short note explaining that "bunx @agentuity/cli secret pull"
is an alternative invocation that maps to "agentuity cloud secret pull"; update
all example lines (the two occurrences that use "bunx @agentuity/cli secret
pull") so they either prepend the missing "cloud" keyword (e.g., "bunx
@agentuity/cli cloud secret pull") or replace them with the canonical "agentuity
cloud secret pull [options]" to remove ambiguity and keep usage/examples
consistent.
- Line 20: The prereq entry "cloud deploy" is ambiguous; update SKILL.md to
clarify that "cloud deploy" refers to the Agentuity CLI command used to deploy
the cloud runtime (i.e., run `agentuity cloud deploy`) and must be executed
before using this skill so the cloud environment and secrets backend exist;
change the bare `cloud deploy` line to a short explanatory sentence mentioning
the specific CLI command name ("agentuity cloud deploy"), its purpose (deploy
cloud runtime/secrets backend), and add a link or pointer to the CLI/docs for
usage and authentication steps.
In @doc-agents/.agents/skills/agentuity-cli-cloud-secret-set/SKILL.md:
- Line 20: The docs mention the --project-id flag as an alternative to running
from a project directory but it’s missing from the Arguments table; update
SKILL.md to either add an optional --project-id entry to the Arguments table
(include its flag name, type, description like "Override current project;
accepts project ID string", and whether it’s required) and mirror this addition
in the related section around lines 28–33, or add a cross-reference to a global
options reference if that’s preferred; ensure the flag name --project-id is
explicitly documented and consistent across the prerequisites and arguments
sections.
- Line 6: Update SKILL.md to use consistent command invocation across Metadata,
Usage, and Examples by either choosing the bare CLI invocation "agentuity cloud
secret set" for docs aimed at globally installed users or showing both forms
with guidance; specifically, change the Metadata line that currently lists
`agentuity cloud secret set` and the Usage line to match the Examples (or vice
versa), and add a short explanatory note under Usage or Examples that shows both
forms — "agentuity cloud secret set" for globally installed installs and "bunx
@agentuity/cli secret set" for running without global install — so readers know
when to use each. Ensure the example blocks (currently using `bunx
@agentuity/cli secret set`) are updated to either mirror the chosen canonical
command or retain both variants with clear context.
- Around line 30-33: Update the SKILL.md argument table to replace the
placeholder "-" entries for `<key>` and `<value>` with concrete guidance: for
`<key>` state the expected format (e.g., uppercase letters, digits and
underscores only, must start with a letter, typical max length ~64 characters)
and that it represents the environment/config key name; for `<value>` state it
accepts UTF-8 strings, recommend a practical max length (e.g., 4k characters),
note that spaces and most special characters are allowed but must be quoted or
escaped in shells, and that multiline values should be provided via proper
quoting, heredoc or encoded (e.g., base64) if the CLI does not support raw
newlines. Include a short note about encoding expectations (UTF-8) and any
recommended quoting/escaping practices so users know how to pass values safely.
- Around line 54-65: The JSON example in SKILL.md uses a string literal for the
success field ("success": "boolean") which mismatches the documented type;
update the example JSON so `success` is a real boolean value (e.g., true or
false) to match the table, leaving `key` and `path` as string examples, and
ensure the sample response block near the `success` field in the file reflects
this change.
In @doc-agents/.agents/skills/agentuity-cli-cloud-session-get/SKILL.md:
- Around line 45-71: The JSON schema in SKILL.md uses "unknown" for several
fields (start_time, end_time, duration, error, timeline, route) which is
ambiguous; update those entries to concrete types or example values—e.g., change
"start_time"/"end_time" to ISO timestamp strings or "string | null", "duration"
to a number (seconds) or "number | null", "error" to "string | null" or an
object like {"code": "...", "message": "..."}, and "timeline"/"route" to
"object" with a small example structure or "object | null"; ensure you update
the entries for start_time, end_time, duration, error, timeline, and route in
the JSON block so consumers know exact types/nullable behavior.
- Around line 29-31: The table row for the `<session_id>` argument in SKILL.md
is missing a description; update the cell for `<session_id>` to explain what
value to supply (e.g., the cloud session identifier/UUID returned by the
Agentuity cloud when a session is created), how to obtain it (from the session
creation response or the web console), and give a short example format (for
example: "123e4567-e89b-12d3-a456-426614174000"); reference the
`agentuity-cli-cloud-session-get` skill name and ensure the wording clarifies it
is required and unique per session.
In @doc-agents/.agents/skills/agentuity-cli-cloud-session-list/SKILL.md:
- Line 59: Replace the inconsistent kebab-case flags in the example invocations
of "bunx @agentuity/cli cloud session list" (the examples containing
"--project-id" and "--deployment-id") with the camelCase variants used in the
options table and other examples: change "--project-id" to "--projectId" and
"--deployment-id" to "--deploymentId" so the example flags match the CLI's
expected option names (also ensure this matches other flags shown like
"--success", "--devmode", "--trigger", "--env").
- Line 80: Replace the phrase "API triggered sessions" with the hyphenated
compound adjective "API-triggered sessions" in the SKILL.md content (the
heading/line containing "Only API triggered sessions") so the adjective
correctly modifies "sessions."
In @doc-agents/.agents/skills/agentuity-cli-cloud-storage-download/SKILL.md:
- Around line 36-66: The README shows a conflicting definition for the
`--metadata` option: the options table marks `--metadata` as Required = "Yes"
but examples use it optionally; update the documentation so the table and
examples match by changing the Required column for `--metadata` to "No" if it is
optional, or make all examples include `--metadata` if it is truly
required—specifically edit the SKILL.md options table entry for `--metadata` to
reflect the correct requirement and adjust examples accordingly to be
consistent.
In @doc-agents/.agents/skills/agentuity-cli-cloud-storage-upload/SKILL.md:
- Around line 39-40: The options table wrongly marks `--key` and `--contentType`
as required despite their descriptions saying they have defaults/are
auto-detected; update the "Required" column for both `--key` and `--contentType`
to "No" in the table (or alternatively remove the default/auto-detect wording if
you intend them to be mandatory) so the table and descriptions are consistent;
ensure the row for `--key` still mentions "defaults to basename or 'stdin' for
piped uploads" and the row for `--contentType` still notes "auto-detected if not
provided."
- Line 53: The example uses the wrong command name; update the example
invocation from "cloud storage put" to the documented command "cloud storage
upload" so it matches the rest of the docs (replace the example line that
currently reads: bunx @agentuity/cli cloud storage put my-bucket file.txt
--content-type text/plain with bunx @agentuity/cli cloud storage upload
my-bucket file.txt --content-type text/plain).
In @doc-agents/.agents/skills/agentuity-cli-cloud-vector-delete/SKILL.md:
- Around line 34-59: Examples in SKILL.md use the wrong command syntax; update
each example invocation to include the missing "cloud" subcommand so they match
the documented usage "agentuity cloud vector delete" (e.g., change "bunx
@agentuity/cli vector delete products chair-001" to use "bunx @agentuity/cli
cloud vector delete products chair-001", similarly update the "vector rm" and
"vector del" examples to "cloud vector rm" and "cloud vector del" with their
existing arguments and --confirm flag).
In
@doc-agents/.agents/skills/agentuity-cli-cloud-vector-list-namespaces/SKILL.md:
- Around line 28-45: The three example commands in SKILL.md are missing the
required "cloud" segment; update each example invocation (the examples showing
"bunx @agentuity/cli vector list-namespaces", "bunx @agentuity/cli vector
namespaces", and "bunx @agentuity/cli vector ns") to include "cloud" immediately
after the package, i.e. change them to "bunx @agentuity/cli cloud vector
list-namespaces", "bunx @agentuity/cli cloud vector namespaces", and "bunx
@agentuity/cli cloud vector ns" so they match the documented usage and command
metadata.
In @doc-agents/.agents/skills/agentuity-cli-cloud-vector-stats/SKILL.md:
- Around line 34-52: Update the example commands in SKILL.md so they match the
documented usage "agentuity cloud vector stats [name]": replace each example
invocation that currently uses "bunx @agentuity/cli vector stats ..." with "bunx
@agentuity/cli cloud vector stats ..." (e.g., update the all-namespaces,
products, and embeddings examples to include the cloud subcommand).
In @doc-agents/.agents/skills/agentuity-cli-profile-use/SKILL.md:
- Line 40: The example command uses the wrong verb "profile switch" and should
use the documented "profile use"; update the example line that currently reads
"bunx @agentuity/cli profile switch staging" to "bunx @agentuity/cli profile use
staging" so the sample matches the CLI's actual "profile use" command.
In @doc-agents/.agents/skills/agentuity-cli-project-create/SKILL.md:
- Line 66: The example shows the undocumented alias "bunx @agentuity/cli project
new --no-register" while the documented primary command is "agentuity project
create"; update SKILL.md so the example uses the primary command ("agentuity
project create --no-register") or, if "new" is an accepted alias, add a brief
note stating that "project new" is an alias of "project create" and show both
forms (e.g., primary first, alias second) so readers aren’t confused.
In @doc-agents/.agents/skills/README.md:
- Line 137: Update the skills README entry that currently says "Show project
detail" to the corrected plural "Show project details"; because this file is
auto-generated, either run the generator command agentuity ai skills generate
--output ./skills to regenerate the README or directly edit the README line
under the "repl" section to replace "detail" with "details".
In @doc-agents/package.json:
- Around line 16-21: Replace all occurrences of "latest" for the listed
dependencies ("@agentuity/react", "@agentuity/runtime", "@agentuity/schema",
"@agentuity/workbench", "@ai-sdk/openai", "ai") in package.json with explicit
semver ranges or exact versions (e.g., ^x.y.z or x.y.z) by looking up the
current desired versions in the npm registry, then run npm install to regenerate
the lockfile; ensure every dependency in that diff is pinned consistently and
verify package.json and package-lock.json (or yarn.lock) are updated before
committing.
- Around line 29-30: The devDependencies in package.json use floating "latest"
versions for @agentuity/cli and @types/bun; replace those with pinned, specific
version strings (e.g., "1.2.3" style) to ensure deterministic builds. Update the
entries for "@agentuity/cli" and "@types/bun" in package.json to concrete semver
values (or exact versions) and run npm/yarn install to regenerate lockfile so CI
uses the pinned versions.
In @doc-agents/src/agent/agent_pulse/context-builder.ts:
- Around line 37-50: In buildCurrentTutorialInfo(tutorials: Tutorial[],
tutorialState?: TutorialState) adjust the completion check to match the
state-manager by changing the condition that uses tutorialState.currentStep vs
currentTutorial.totalSteps from a strict greater-than to greater-than-or-equal;
specifically update the if in buildCurrentTutorialInfo so it treats currentStep
>= totalSteps as completed to avoid the off-by-one mismatch with the
state-manager logic.
- Around line 7-32: The tutorial list returned by getTutorialList and embedded
by buildContext is not runtime-validated or sanitized; add a Zod schema for the
Tutorial shape in the module that parses the API response (the code that
currently casts to `as Tutorial[]` in tutorial.ts), validate the parsed payload
and reject or coerce invalid entries, then ensure buildContext uses the
validated result (the value returned by getTutorialList) and sanitizes all
string fields (title, description, difficulty, etc.) before embedding—e.g.,
trim, remove control/chars that could inject prompts, and escape or redact
suspicious tokens—so update tutorial parsing to run Zod.parse/ safeParse and
update buildContext (and buildCurrentTutorialInfo if it formats fields) to call
a small sanitizeString helper on every string field prior to JSON.stringify or
interpolation, falling back to defaultFallbackContext on validation failure.
- Around line 85-87: The TOOL-USAGE RULES comment incorrectly names
startTutorialById; update the instruction to reference the actual tool
startTutorialAtStep and clarify its behavior (use when the user selects a
tutorial; for new tutorials set step=1 and validate step is between 1 and the
tutorial's totalSteps). Also ensure any mention of startTutorialById in the same
comment block or nearby logic is replaced with startTutorialAtStep to avoid
confusion for the agent.
In @doc-agents/src/api/title-generator/route.ts:
- Around line 54-102: The POST handler at router.post('/') is missing
authentication; import the existing bearerTokenAuth (symbol: bearerTokenAuth)
and apply it as middleware on the route (i.e., router.post('/', bearerTokenAuth,
async (c) => ...) so the request is authenticated before calling
generateText/openai; update the file imports to include bearerTokenAuth and
ensure the route signature still uses the async handler (router.post). Also add
or wire a rate-limiting middleware (e.g., a shared rateLimit middleware used
across OpenAI endpoints) to this route to protect against abuse.
- Around line 38-42: The sentenceCase function currently lowercases the whole
string then capitalizes the first character, which destroys intended
capitalization; update sentenceCase to preserve the original capitalization of
the rest of the string by removing the toLowerCase() step and returning
str.charAt(0).toUpperCase() + str.slice(1) (leave the empty-check intact) so
proper nouns and acronyms (e.g., "API Reference Guide") are not altered.
In @lib/api/services/agentPulse.ts:
- Around line 119-131: The final buffer handling block only parses text-delta
and finish types; update it to mirror the main SSE parsing logic by handling all
StreamingChunk types — at minimum check for 'text-delta' (call
callbacks.onTextDelta with chunk.textDelta), 'finish' (callbacks.onFinish),
'status' (callbacks.onStatus or equivalent), 'tutorial-data'
(callbacks.onTutorialData), and 'error' (callbacks.onError) — and include safe
existence checks before invoking each callback; use the existing StreamingChunk
type, buffer parsing (JSON.parse(buffer.slice(6))), and the callbacks object to
ensure consistent behavior with the main loop.
In @lib/api/services/agentQa.ts:
- Around line 12-15: The AgentQaResponse interface is currently not exported but
is intended for public use; modify the declaration of AgentQaResponse in
agentQa.ts so it is exported (e.g., add the export keyword before the interface
or export it as a type alias) so the symbol AgentQaResponse is available for the
existing re-export in lib/api/services/index.ts.
In @lib/kv-store.ts:
- Around line 27-29: The exported interface KVDeleteResult is unused because
deleteKVValue currently returns Promise<boolean>; either remove the
KVDeleteResult declaration or change deleteKVValue's signature to return
Promise<KVDeleteResult> and adapt its implementation to return an object
matching { exists: boolean } (update any call sites accordingly); reference the
KVDeleteResult interface and the deleteKVValue function to locate and apply the
change.
- Around line 55-57: Remove the debug console.log in the code that prints
serviceUrls; specifically, delete the line console.log('serviceUrls',
serviceUrls) located where getServiceUrls() is called and before returning new
KeyValueStorageService(serviceUrls.keyvalue, adapter) so the function returns
only the KeyValueStorageService instance without emitting debug output.
In @lib/tutorial/state-manager.ts:
- Around line 90-100: completeTutorial currently creates two separate Date()
instances and silently ignores failures from setKVValue; change it to create a
single timestamp variable (e.g., const now = new Date().toISOString()) and
assign that to both state.tutorials[tutorialId].completedAt and .lastAccessedAt,
then await setKVValue inside a try/catch and log any error (include error
details) instead of swallowing it—use the same logging approach used by
updateTutorialProgress and reference getUserTutorialState and getTutorialKey to
locate the surrounding code.
🟡 Minor comments (27)
doc-agents/.agents/skills/agentuity-cli-cloud-storage-upload/SKILL.md-53-53 (1)
53-53: Fix the command name in the example.Line 53 uses
cloud storage put, but the command signature defined throughout the documentation iscloud storage upload. Update the example for consistency.-bunx @agentuity/cli cloud storage put my-bucket file.txt --content-type text/plain +bunx @agentuity/cli cloud storage upload my-bucket file.txt --content-type text/plaindoc-agents/.agents/skills/agentuity-cli-cloud-env-delete/SKILL.md-28-32 (1)
28-32: Provide a description for the<key>argument.The argument table on line 32 has an empty description for
<key>. Clarify what this argument represents (e.g., "Environment variable name" or "Key of the environment variable to delete").🔎 Proposed fix for argument description
| Argument | Type | Required | Description | |----------|------|----------|-------------| -| `<key>` | string | Yes | - | +| `<key>` | string | Yes | Environment variable key to delete |doc-agents/.agents/skills/agentuity-cli-cloud-session-list/SKILL.md-80-80 (1)
80-80: Use hyphenation for compound adjective.Line 80 reads "API triggered sessions" but should be "API-triggered sessions" to properly hyphenate the compound adjective modifying "sessions".
🔎 Proposed fix for hyphenation
-Only API triggered sessions: +Only API-triggered sessions:doc-agents/.agents/skills/agentuity-cli-cloud-secret-set/SKILL.md-20-20 (1)
20-20: Document the--project-idflag mentioned in prerequisites.Line 20 references the
--project-idflag as an alternative to running from a project directory, but it's not included in the Arguments table. Either add it as an optional argument or provide its documentation elsewhere (e.g., in a global options reference).Also applies to: 28-33
doc-agents/.agents/skills/agentuity-cli-cloud-secret-set/SKILL.md-6-6 (1)
6-6: Reconcile inconsistent command invocation across sections.The documented command varies across sections:
- Metadata (line 9):
agentuity cloud secret set- Usage (line 25):
agentuity cloud secret set- Examples (lines 40, 46):
bunx @agentuity/cli secret setClarify whether users should invoke via the bare
agentuitycommand, thebunx @agentuity/cliwrapper, or both. If both are valid, explain when each is appropriate (e.g., with/without global installation).Also applies to: 9-9, 24-25, 40-40, 46-46
doc-agents/.agents/skills/agentuity-cli-cloud-secret-set/SKILL.md-30-33 (1)
30-33: Complete argument descriptions.Argument descriptions are empty (shown as "-"). Provide meaningful guidance on:
- What format or values
<key>should take (e.g., uppercase with underscores likeDATABASE_URL)?- What constraints apply to
<value>(length limits, character restrictions, encoding)?- Whether values can contain spaces, special characters, or newlines?
This information is critical for users to invoke the command correctly.
doc-agents/.agents/skills/agentuity-cli-cloud-secret-set/SKILL.md-54-65 (1)
54-65: Fix the type mismatch in the output schema.The JSON example (line 54–59) shows
"success": "boolean"(a string literal), but the field description table (line 62–63) lists the type asboolean. This is a critical inconsistency that will confuse users about the actual response format.Correct the JSON example to match the intended schema:
🔎 Proposed fix
```json { - "success": "boolean", + "success": true, "key": "string", "path": "string" }</details> </blockquote></details> <details> <summary>doc-agents/.agents/skills/agentuity-cli-cloud-secret-pull/SKILL.md-20-20 (1)</summary><blockquote> `20-20`: **Clarify the "cloud deploy" prerequisite.** Line 20 lists `cloud deploy` as a prerequisite but provides no explanation. It's unclear whether this refers to a deployment service, a prerequisite command, or something else. Provide additional context to help users understand this requirement. </blockquote></details> <details> <summary>doc-agents/.agents/skills/agentuity-cli-cloud-session-get/SKILL.md-29-31 (1)</summary><blockquote> `29-31`: **Add description for the `<session_id>` argument.** The argument description is missing (only a dash). Users need guidance on what values to provide or examples of a valid session ID format. <details> <summary>🔎 Suggested improvement</summary> ```diff | Argument | Type | Required | Description | |----------|------|----------|-------------| -| `<session_id>` | string | Yes | - | +| `<session_id>` | string | Yes | The unique identifier of the session to retrieve (e.g., `sess_abc123xyz`) |doc-agents/.agents/skills/agentuity-cli-cloud-agent-get/SKILL.md-35-35 (1)
35-35: Fix example description to match context.The example description says "Get item details" but the command retrieves agent details. Update to maintain consistency.
🔎 Proposed fix
-Get item details: +Get agent details:doc-agents/.agents/skills/agentuity-cli-cloud-agent-get/SKILL.md-29-31 (1)
29-31: Add meaningful description for the<agent_id>argument.The Argument table at line 31 shows only a dash "-" for the Description. Provide a clear explanation of what
<agent_id>is and how to obtain it.🔎 Proposed fix
| Argument | Type | Required | Description | |----------|------|----------|-------------| -| `<agent_id>` | string | Yes | - | +| `<agent_id>` | string | Yes | The unique identifier of the agent to retrieve |doc-agents/.agents/skills/agentuity-cli-cloud-storage-download/SKILL.md-36-66 (1)
36-66: Resolve conflicting--metadataoption definition.The options table marks
--metadataas Required = "Yes" (line 40), but the examples show it being used optionally—it appears in only one of four examples (line 65). Either the option is required (and all examples should include it) or it's optional (and the table should mark Required = "No").doc-agents/.agents/skills/agentuity-cli-cloud-deployment-rollback/SKILL.md-16-20 (1)
16-20: Clarify the prerequisite on line 19.The prerequisite "cloud deploy" is unclear. Specify whether it's a skill dependency, a configuration requirement, or something else.
doc-agents/.agents/skills/agentuity-cli-cloud-deploy/SKILL.md-16-20 (1)
16-20: Remove malformed prerequisite text on line 20.Line 20 contains only
- auth login, which appears to be a duplicate or corrupted entry. The required authentication is already documented on line 18. This should be removed.🔎 Proposed fix
## Prerequisites - Authenticated with `agentuity auth login` - Project context required (run from project directory or use `--project-id`) -- auth logindoc-agents/.agents/skills/agentuity-cli-profile-use/SKILL.md-40-40 (1)
40-40: Fix incorrect command verb in example.The example on line 40 uses
profile switchinstead of the documentedprofile usecommand. This will fail if users copy the example as-is.🔎 Proposed fix
Switch to the "staging" profile: ```bash - bunx @agentuity/cli profile switch staging + bunx @agentuity/cli profile use staging</details> <!-- review_comment_end] --> <!-- [scratchpad_start] [task review_file_3/3] File 3 review complete. [scratchpad_end] --> </blockquote></details> <details> <summary>doc-agents/.agents/skills/agentuity-cli-project-create/SKILL.md-66-66 (1)</summary><blockquote> `66-66`: **Clarify the `project new` command usage.** Line 66 shows `bunx @agentuity/cli project new --no-register`, but the documented command is `agentuity project create`. If `new` is an alias for `create`, this should be explicitly documented in a note or the example should use the primary `create` command. </blockquote></details> <details> <summary>doc-agents/.agents/skills/agentuity-cli-cloud-keyvalue-keys/SKILL.md-24-52 (1)</summary><blockquote> `24-52`: **Document all command aliases consistently in the keys skill examples.** The Usage section (`agentuity cloud keyvalue keys`) and Examples section (`bunx @agentuity/cli kv`) intentionally document different execution methods—the Usage section shows the canonical syntax while Examples demonstrate the package runner shorthand. This pattern is consistent across all keyvalue skills. However, within the keys skill's examples, aliases are labeled inconsistently: "kv ls" is marked "(using alias)" but "kv list" appears without any label despite being a separate alias. For clarity, either label all aliases uniformly or remove inconsistent labels to match the pattern used in other skills (where aliases may be shown without explicit labels). </blockquote></details> <details> <summary>doc-agents/.agents/skills/README.md-137-137 (1)</summary><blockquote> `137-137`: **Fix grammatical issue in skills table.** Line 137 shows "Show project detail" which should be "Show project details" (plural noun). Since this is an auto-generated file, regenerating via `agentuity ai skills generate --output ./skills` should correct this automatically. </blockquote></details> <details> <summary>doc-agents/.agents/skills/agentuity-cli-cloud-keyvalue-delete/SKILL.md-28-33 (1)</summary><blockquote> `28-33`: **Add descriptions for command arguments.** The arguments table lacks descriptions for both `<namespace>` and `<key>`. Provide context about what each argument represents (e.g., what namespaces are available, format expectations). </blockquote></details> <details> <summary>doc-agents/.agents/skills/agentuity-cli-cloud-keyvalue-delete/SKILL.md-35-53 (1)</summary><blockquote> `35-53`: **Clarify relationship between documented command and example aliases.** The usage section documents the full command `agentuity cloud keyvalue delete`, but all examples use shorter aliases (`kv delete`, `kv rm`). If these are official shortcuts, they should be mentioned in the Usage section. If not, examples should demonstrate the primary command form. </blockquote></details> <details> <summary>doc-agents/src/api/title-generator/route.ts-38-42 (1)</summary><blockquote> `38-42`: **Sentence case may alter intentional capitalization.** The `sentenceCase` function converts the entire string to lowercase before capitalizing the first character (line 40). This will incorrectly lowercase proper nouns, acronyms, and intentionally capitalized words (e.g., "API Reference Guide" becomes "Api reference guide"). <details> <summary>🔎 Proposed fix to preserve existing capitalization</summary> ```diff function sentenceCase(str: string): string { if (!str) return ''; - const lower = str.toLowerCase(); - return lower.charAt(0).toUpperCase() + lower.slice(1); + // Only capitalize first letter, preserve rest + return str.charAt(0).toUpperCase() + str.slice(1); }doc-agents/src/agent/agent_pulse/context-builder.ts-85-87 (1)
85-87: Fix tool name mismatch in instructions.Line 86 references
startTutorialByIdbut the actual tool name isstartTutorialAtStep(as seen indoc-agents/src/agent/agent_pulse/tools.ts). This mismatch could confuse the AI model about which tool to use.🔎 Proposed fix
=== TOOL-USAGE RULES (must follow) === -- startTutorialById must only be used when user select a tutorial. If the user starts a new tutorial, the step number should be set to one. Valid step is between 1 and totalSteps of the specific tutorial. +- startTutorialAtStep must only be used when user select a tutorial. If the user starts a new tutorial, the step number should be set to one. Valid step is between 1 and totalSteps of the specific tutorial. - Treat askDocsAgentTool as a search helper; ignore results you judge irrelevant.lib/kv-store.ts-27-29 (1)
27-29:KVDeleteResultinterface is defined but unused.The
KVDeleteResultinterface is exported butdeleteKVValuereturnsPromise<boolean>instead. Either use this interface as the return type or remove it.lib/kv-store.ts-55-57 (1)
55-57: Remove debugconsole.logstatement.Line 56 contains a debug log (
console.log('serviceUrls', serviceUrls)) that should be removed before merging to production.🔎 Proposed fix
const serviceUrls = getServiceUrls(); - console.log('serviceUrls', serviceUrls); return new KeyValueStorageService(serviceUrls.keyvalue, adapter);lib/api/services/agentPulse.ts-119-131 (1)
119-131: Incomplete handling of chunk types in final buffer processing.The final buffer processing only handles
text-deltaandfinishchunk types, but the main loop handlesstatus,tutorial-data, anderroras well. If the last SSE event is one of these types, it will be silently ignored.🔎 Proposed fix to handle all chunk types consistently
// Process any remaining data if (buffer.length > 0 && buffer.startsWith('data: ')) { try { const chunk = JSON.parse(buffer.slice(6)) as StreamingChunk; if (chunk.type === 'text-delta' && chunk.textDelta) { callbacks.onTextDelta?.(chunk.textDelta); + } else if (chunk.type === 'status') { + callbacks.onStatus?.(chunk.message || '', chunk.category); + } else if (chunk.type === 'tutorial-data' && chunk.tutorialData) { + callbacks.onTutorialData?.(chunk.tutorialData); } else if (chunk.type === 'finish') { callbacks.onFinish?.(); + } else if (chunk.type === 'error') { + callbacks.onError?.(chunk.error || 'Unknown error'); } } catch (error) { console.error('Error parsing final SSE chunk:', error); } }app/api/sessions/[sessionId]/messages/route.ts-16-16 (1)
16-16: Unused constantAGENT_REQUEST_TIMEOUT.
AGENT_REQUEST_TIMEOUTis defined but never used in this file. The timeout is now handled internally bycallAgentPulseStreaming. Remove this dead code.🔎 Proposed fix
// Constants const DEFAULT_CONVERSATION_HISTORY_LIMIT = 10; -const AGENT_REQUEST_TIMEOUT = 30000; // 30 secondslib/tutorial/state-manager.ts-90-100 (1)
90-100:completeTutorialsilently ignores KV write failures.Unlike
updateTutorialProgresswhich logs on failure,completeTutorialdoesn't check or log the result ofsetKVValue. Additionally, lines 94-95 create two separateDateobjects when a single timestamp could be reused.🔎 Proposed fix
async function completeTutorial(userId: string, tutorialId: string): Promise<void> { const state = await getUserTutorialState(userId); if (state.tutorials[tutorialId]) { - state.tutorials[tutorialId].completedAt = new Date().toISOString(); - state.tutorials[tutorialId].lastAccessedAt = new Date().toISOString(); + const now = new Date().toISOString(); + state.tutorials[tutorialId].completedAt = now; + state.tutorials[tutorialId].lastAccessedAt = now; const key = getTutorialKey(userId); - await setKVValue(key, state, { storeName: config.kvStoreName }); + const success = await setKVValue(key, state, { storeName: config.kvStoreName }); + if (!success) { + console.error(`Failed to complete tutorial. UserId: ${userId}, TutorialId: ${tutorialId}`); + } } }
🧹 Nitpick comments (28)
doc-agents/.agents/skills/agentuity-cli-cloud-thread-get/SKILL.md (1)
45-69: Clarify "unknown" type annotations in the output schema.The JSON schema and table (lines 51-52, 55, 65-66) document several fields with type
"unknown"(deleted_at,deleted_by,user_data). For API consumers, these should be more specific: isuser_dataa JSON object, string, or null? Aredeleted_atanddeleted_byalso nullable fields?Provide explicit type definitions or note when fields are optional/nullable to improve clarity.
doc-agents/.agents/skills/agentuity-cli-cloud-storage-upload/SKILL.md (1)
30-33: Add descriptions for arguments.The Arguments table for
<name>and<filename>lacks descriptions in the "Description" column. Consider adding clarifications (e.g., is<name>the bucket name? Is<filename>a local or remote path?).doc-agents/.agents/skills/agentuity-cli-cloud-apikey-get/SKILL.md (2)
33-38: Provide a concrete example ID in the example.The example uses the placeholder
<id>without showing what a real API key ID looks like. Consider showing a concrete example ID (e.g.,api_key_12345abc) to help users understand the expected format.
1-38: Add an Output section for consistency with related skills.The create skill documents the output JSON schema; consider adding an Output section here to document what the GET response looks like and clarify whether it returns the full API key object, metadata only, or another structure.
doc-agents/.agents/skills/agentuity-cli-cloud-session-get/SKILL.md (1)
73-97: Enhance field descriptions with more actionable guidance.Several descriptions are generic or merely repeat field names (e.g., "Thread ID" for
thread_id, "Error message" forerror). Adding more context—such as when fields are null, what they represent in the execution flow, or how to use them—would improve usability.🔎 Example improvements
-| `error` | unknown | Error message | +| `error` | unknown | Error message, if session failed; null if successful | -| `timeline` | unknown | Session timeline | +| `timeline` | unknown | Ordered list of session execution events with timestamps | -| `thread_id` | string | Thread ID | +| `thread_id` | string | Unique conversation thread ID for multi-turn interactions |doc-agents/.agents/skills/agentuity-cli-cloud-db-sql/SKILL.md (1)
13-13: Fix heading capitalization for consistency.The heading "# Cloud Db Sql" uses inconsistent casing. For standard Markdown conventions, it should be "# Cloud DB SQL" (acronym capitalized) or "# Cloud Database SQL".
🔎 Proposed fix
-# Cloud Db Sql +# Cloud DB SQLdoc-agents/.agents/skills/agentuity-cli-profile-create/SKILL.md (1)
37-41: Clarify example descriptions for distinct use cases.Examples on lines 37 and 49 both use the same description "Create new item:" but demonstrate different profiles (production vs. development). Rename these to reflect the profile context or use case difference for better clarity.
🔎 Proposed improvements
## Examples - Create new item: + Create production profile: ```bash bunx @agentuity/cli profile create productionUse switch option:
bunx @agentuity/cli profile create staging --switch
- Create new item:
Create development profile:
bunx @agentuity/cli profile create development</details> <!-- review_comment_end] --> <!-- [scratchpad_start] [task review_file_2/3] File 2 review complete. [scratchpad_end] --> Also applies to: 49-53 </blockquote></details> <details> <summary>doc-agents/.agents/skills/agentuity-cli-auth-login/SKILL.md (1)</summary><blockquote> `24-34`: **Clarify example descriptions and consider documenting output.** Both examples have identical descriptions ("Login to account:"), making it unclear what distinguishes them. The first uses the full command path while the second uses an alias shortcut. Additionally, consider documenting the expected output or behavior after successful login (similar to the output schema in other SKILL.md files like `agentuity-cli-cloud-keyvalue-get`). <details> <summary>💡 Suggested improvement</summary> ```diff -Login to account: +Login using full command: ```bash bunx @agentuity/cli auth login-Login to account:
+Login using shorthand alias:bunx @agentuity/cli login
+## Output
+
+Opens default browser for authentication. Upon success, credentials are stored locally and confirmed in terminal.</details> </blockquote></details> <details> <summary>doc-agents/.agents/skills/agentuity-cli-cloud-keyvalue-get/SKILL.md (1)</summary><blockquote> `30-33`: **Add descriptions for command arguments.** The Arguments table lists `<namespace>` and `<key>` as required but provides no description (shows "-"). Adding brief descriptions would improve usability. <details> <summary>📝 Suggested descriptions</summary> ```diff | Argument | Type | Required | Description | |----------|------|----------|-------------| -| `<namespace>` | string | Yes | - | -| `<key>` | string | Yes | - | +| `<namespace>` | string | Yes | The keyvalue namespace to query | +| `<key>` | string | Yes | The key to retrieve from the namespace |doc-agents/.agents/skills/agentuity-cli-cloud-keyvalue-list-namespaces/SKILL.md (1)
47-49: Consider adding output schema details.The output section only states
Returns: arraywithout describing the structure of the array elements. Adding details about what each array item contains would improve the documentation's usefulness.📋 Example enhancement
## Output -Returns: `array` +Returns an array of namespace strings: + +```json +["production", "staging", "cache"] +``` + +Each element is a string representing a keyvalue namespace name.doc-agents/.agents/skills/agentuity-cli-auth-ssh-list/SKILL.md (1)
28-38: Duplicate example section headers reduce clarity.Lines 28 and 34 both use "List items:" as section headers, but they show different command variants (primary and alias). Users reading the documentation would see identical labels for distinct examples, making it unclear which form to use.
Consider differentiation like:
- "List items using primary command:" (line 28)
- "List items using alias:" (line 34)
doc-agents/.agents/skills/agentuity-cli-auth-logout/SKILL.md (1)
24-34: Duplicate example section headers and missing output schema.Similar to the auth-ssh-list file, lines 24 and 30 both use "Logout from account:" for different command forms. Additionally, this file lacks an output schema specification (see
agentuity-cli-auth-ssh-list/SKILL.mdline 46 for comparison). Consider adding an## Outputsection describing what the logout command returns.doc-agents/.agents/skills/agentuity-cli-cloud-keyvalue-delete-namespace/SKILL.md (1)
13-15: Normalize heading formatting to match command syntax.Line 13 presents the heading as "Cloud Keyvalue Delete-namespace" (inconsistent capitalization), while the actual command syntax on line 25 and throughout uses "keyvalue delete-namespace" (lowercase). For consistency with the command structure and other documentation, consider: "# Cloud Keyvalue Delete-Namespace" or follow the exact command name format.
lib/api/services/titleGenerator.ts (2)
8-11: Consider extracting shared types to a common location.The
ConversationMessageinterface is duplicated indoc-agents/src/agent/agent_pulse/types.ts(lines 0-3). Consider extracting this to a shared types file to maintain a single source of truth and prevent drift between definitions.🔎 Suggested approach
Create a shared types file (e.g.,
lib/types/conversation.ts):export interface ConversationMessage { author: 'USER' | 'ASSISTANT'; content: string; }Then import from both locations:
-interface ConversationMessage { - author: 'USER' | 'ASSISTANT'; - content: string; -} +import type { ConversationMessage } from '@/lib/types/conversation';
33-33: Handle empty string response from API.Line 33 returns
response.title || 'New chat', which correctly handlesundefinedandnull, but an empty string''from the API would also fall back to the default. Consider explicitly checking for a meaningful title to avoid accepting whitespace-only responses.🔎 Suggested refinement
- return response.title || 'New chat'; + return response.title?.trim() || 'New chat';doc-agents/src/api/title-generator/route.ts (1)
24-24: Complex regex pattern needs validation.The markdown emphasis removal regex on Line 24 uses multiple capture groups and may not handle all edge cases (e.g., unbalanced markers, nested emphasis). Consider testing with various inputs including malformed markdown.
🔎 Test cases to verify
// Test cases for sanitizeTitle const testCases = [ '**bold** and *italic*', '**unbalanced bold', 'nested **bold *and italic* text**', '___triple underscore___', ];doc-agents/src/agent/agent_pulse/agent.ts (1)
9-16: Schema duplication: conversation history structure defined inline.The conversation history schema (lines 11-14) duplicates the structure already defined in
doc-agents/src/agent/agent_pulse/types.ts(ConversationMessage interface). This creates a third definition alongside the one inlib/api/services/titleGenerator.ts.Consider reusing the shared type definition or creating a schema from the TypeScript interface to maintain consistency.
lib/api/types.ts (1)
13-22: Remove redundant type annotation.The type annotation on Line 16 is trivially inferred from its initialization value.
🔎 Proposed fix
constructor( message: string, - public status: number = 500, + public status = 500, public details?: unknown ) {doc-agents/src/agent/agent_pulse/tools.ts (1)
26-31: Improve error message and remove unnecessary template literal.Line 30 uses a template literal without interpolation. Additionally, the error message "Error fetching tutorial information" is too generic and doesn't provide helpful context to the user.
🔎 Proposed fix
// Validate tutorial exists before starting const tutorialResponse = await getTutorialMeta(tutorialId, agentContext); if (!tutorialResponse.success || !tutorialResponse.data) { - return `Error fetching tutorial information`; + return `Unable to find tutorial "${tutorialId}". Please verify the tutorial ID is correct.`; }lib/api/services/agentQa.ts (1)
8-10: Remove unused interface.The
AgentQaRequestinterface is defined but never used. The request body on Line 28 is constructed as an inline object literal.🔎 Proposed fix
-interface AgentQaRequest { - message: string; -} - interface AgentQaResponse { answer: string; documents?: string[]; }Alternatively, if you want to maintain type safety for the request body, use it:
interface AgentQaRequest { message: string; } interface AgentQaResponse { answer: string; documents?: string[]; } const AGENT_QA_TIMEOUT = 30000; // 30 seconds export async function queryAgentQa(message: string): Promise<AgentQaResponse> { try { + const requestBody: AgentQaRequest = { message }; const response = await apiRequest<AgentQaResponse>( '/api/doc-qa', { method: 'POST', - body: { message }, + body: requestBody, timeout: AGENT_QA_TIMEOUT, }, undefined, // use default baseUrl from config process.env.AGENT_BEARER_TOKEN );doc-agents/src/agent/agent_pulse/tutorial.ts (1)
49-113: Solid error handling and type mapping.The function follows the same robust error handling pattern as
getTutorialListand correctly validates the nested response structure before accessing the data.The inline type definition (lines 75-86) is verbose but provides type safety. If this response structure is reused elsewhere, consider extracting it to a shared type.
💡 Optional: Extract response type if reused
If this response structure is used in multiple places:
interface TutorialApiResponse { id: string; metadata: { title: string; description: string; totalSteps: number; difficulty?: string; estimatedTime?: string; }; fullContent: string; steps: Array<{ stepNumber: number; title: string; estimatedTime?: string }>; } export async function getTutorialMeta(tutorialId: string, ctx: any): Promise<ApiResponse<Tutorial>> { // ... const responseData = (await response.json()) as ApiResponse<TutorialApiResponse>; // ... }lib/api/client.ts (1)
11-14: Consider normalizing base URL to handle trailing slashes.The
buildUrlfunction doesn't account for trailing slashes inbaseUrl. IfbaseUrlis"http://example.com/"andendpointis"/api/test", the result will be"http://example.com//api/test"(double slash). While most HTTP clients handle this gracefully, it's better to be explicit.🔎 Proposed fix
function buildUrl(baseUrl: string, endpoint: string): string { + const cleanBase = baseUrl.endsWith('/') ? baseUrl.slice(0, -1) : baseUrl; const cleanEndpoint = endpoint.startsWith('/') ? endpoint : `/${endpoint}`; - return `${baseUrl}${cleanEndpoint}`; + return `${cleanBase}${cleanEndpoint}`; }doc-agents/src/api/agent_pulse/route.ts (1)
55-75: Improve type safety by avoidingas anycasts.Multiple
as anycasts appear throughout this section (lines 55, 64, 70, 75), which bypass TypeScript's type checking. While this might be expedient, it reduces type safety and could hide bugs.Consider defining proper types for the state and context objects used by
createTools,buildContext, andbuildSystemPrompt.💡 Example type definitions
interface AgentContext { logger: { info: (msg: string, ...args: any[]) => void; warn: (msg: string, ...args: any[]) => void; error: (msg: string, ...args: any[]) => void; debug: (msg: string, ...args: any[]) => void; }; } interface ToolState { action: Action | null; } // Then use these types instead of 'as any' const state: ToolState = { action: null }; const agentContext: AgentContext = { logger };lib/api/services/agentPulse.ts (1)
24-40: Consider stronger typing fortutorialDatafields.The
tutorialDatafields on lines 29 and 37 useany, which bypasses TypeScript's type checking. Consider using a more specific type or at leastunknownto enforce type checking at usage sites.doc-agents/src/agent/agent_pulse/types.ts (3)
39-47: DuplicateStreamingChunktype definition with differingtutorialDatatyping.This
StreamingChunkinterface is also defined inlib/api/services/agentPulse.ts(lines 23-31), but with different typing fortutorialData:
- Here:
tutorialData?: Action(strongly typed)- There:
tutorialData?: any(loosely typed)Consider consolidating these types into a shared location to ensure consistency and prevent drift.
1-9: Consider consolidating duplicate type definitions.
ConversationMessageandTutorialStateare also defined inlib/api/services/agentPulse.ts(lines 8-16). Having parallel definitions increases maintenance burden and risks divergence. Consider sharing these types from a single source.
20-26: Consider usingunknowninstead ofanyfordetailsfield.Using
unknowninstead ofanyfor thedetailsfield would enforce explicit type checking when accessing this property, improving type safety.lib/kv-store.ts (1)
42-58: Service re-initialization on every KV operation impacts performance.
initializeKVService()creates a newKeyValueStorageServiceinstance on everyget,set, anddeletecall. This involves creating a new fetch adapter and potentially redundant setup work. Consider caching the service instance at module level with lazy initialization.🔎 Proposed refactor to cache the service instance
+let kvServiceInstance: KeyValueStorageService | null = null; + // Initialize the KV service function initializeKVService() { + if (kvServiceInstance) { + return kvServiceInstance; + } + if (!process.env.AGENTUITY_SDK_KEY) { throw new Error('AGENTUITY_SDK_KEY environment variable is required'); } const adapter = createServerFetchAdapter({ headers: { Authorization: `Bearer ${process.env.AGENTUITY_SDK_KEY}`, 'User-Agent': 'Next.js App/1.0', }, }, logger); const serviceUrls = getServiceUrls(); - console.log('serviceUrls', serviceUrls); - return new KeyValueStorageService(serviceUrls.keyvalue, adapter); + kvServiceInstance = new KeyValueStorageService(serviceUrls.keyvalue, adapter); + return kvServiceInstance; }Also applies to: 73-74, 109-111, 132-133
| | Option | Type | Required | Default | Description | | ||
| |--------|------|----------|---------|-------------| | ||
| | `--file` | string | Yes | - | File containing the public key | | ||
|
|
||
| ## Examples | ||
|
|
||
| Add SSH key interactively: | ||
|
|
||
| ```bash | ||
| bunx @agentuity/cli auth ssh add | ||
| ``` |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🧩 Analysis chain
🏁 Script executed:
fd "SKILL.md" doc-agents/.agents/skills/agentuity-cli-auth-ssh-add/ --type fRepository: agentuity/docs
Length of output: 119
🏁 Script executed:
cat -n "doc-agents/.agents/skills/agentuity-cli-auth-ssh-add/SKILL.md"Repository: agentuity/docs
Length of output: 2143
Resolve inconsistency between required --file flag and examples that omit it.
The options table marks --file as required, but multiple examples contradict this: the "Add SSH key interactively" example (line 37) and "Add SSH key from stdin" example (line 55) both omit the flag. The description on line 14 states the command "reads from file or stdin", suggesting the flag should be optional. Either mark --file as optional in the table, or update all examples to include it with clear documentation of input methods.
🤖 Prompt for AI Agents
In @doc-agents/.agents/skills/agentuity-cli-auth-ssh-add/SKILL.md around lines
28 - 38, The options table incorrectly marks `--file` as required while examples
for "Add SSH key interactively" and "Add SSH key from stdin" omit it; update
SKILL.md so the table marks `--file` as optional (change "Yes" to "No" or
"Optional") and add a short note in the table or header that the command reads
from stdin when `--file` is not provided, or alternatively update the examples
to always include `--file` and show the stdin/interactive variants explicitly
(modify the "Add SSH key interactively" and "Add SSH key from stdin" examples to
either include `--file <path>` or annotate that stdin/interactive mode is used).
|
|
||
| ```json | ||
| { | ||
| "id": "string", | ||
| "name": "string", | ||
| "description": "unknown", | ||
| "identifier": "string", | ||
| "deploymentId": "unknown", | ||
| "devmode": "boolean", | ||
| "metadata": "unknown", | ||
| "createdAt": "string", | ||
| "updatedAt": "string", | ||
| "evals": "array" | ||
| } | ||
| ``` | ||
|
|
||
| | Field | Type | Description | | ||
| |-------|------|-------------| | ||
| | `id` | string | - | | ||
| | `name` | string | - | | ||
| | `description` | unknown | - | | ||
| | `identifier` | string | - | | ||
| | `deploymentId` | unknown | - | | ||
| | `devmode` | boolean | - | | ||
| | `metadata` | unknown | - | | ||
| | `createdAt` | string | - | | ||
| | `updatedAt` | string | - | | ||
| | `evals` | array | - | |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🧩 Analysis chain
🏁 Script executed:
# First, let's check if the file exists and read it
find . -name "SKILL.md" -path "*/agentuity-cli-cloud-agent-get/*" 2>/dev/null | head -5Repository: agentuity/docs
Length of output: 124
🏁 Script executed:
# List files in the agent directory to understand structure
ls -la doc-agents/.agents/skills/agentuity-cli-cloud-agent-get/ 2>/dev/null || echo "Path not found, searching for similar directories"Repository: agentuity/docs
Length of output: 229
🏁 Script executed:
# Search for SKILL.md files to understand the pattern
fd "SKILL\.md" doc-agents/ 2>/dev/null | head -10Repository: agentuity/docs
Length of output: 40
🏁 Script executed:
cat -n doc-agents/.agents/skills/agentuity-cli-cloud-agent-get/SKILL.mdRepository: agentuity/docs
Length of output: 2132
🏁 Script executed:
# Check for auto-generation markers in the file
head -20 doc-agents/.agents/skills/agentuity-cli-cloud-agent-get/SKILL.mdRepository: agentuity/docs
Length of output: 567
🏁 Script executed:
# Search for similar SKILL.md files to see if they also have "unknown" types
fd "SKILL\.md" doc-agents/ -x grep -l "unknown" {} \; 2>/dev/nullRepository: agentuity/docs
Length of output: 40
🏁 Script executed:
# Search for all SKILL.md files and check which ones have "unknown" types
fd "SKILL\.md" doc-agents/ -x grep -c "unknown" {} + | grep -v ":0$"Repository: agentuity/docs
Length of output: 40
🏁 Script executed:
# Get a count of SKILL.md files with and without "unknown" types
echo "=== Files with 'unknown' type ===" && \
fd "SKILL\.md" doc-agents/ -x grep -l "unknown" {} \; | wc -l && \
echo "=== Total SKILL.md files ===" && \
fd "SKILL\.md" doc-agents/ | wc -lRepository: agentuity/docs
Length of output: 124
🏁 Script executed:
# Look for any generation markers or comments in multiple SKILL.md files
fd "SKILL\.md" doc-agents/ | head -5 | xargs -I {} sh -c 'echo "=== {} ===" && head -15 {}'Repository: agentuity/docs
Length of output: 40
🏁 Script executed:
# Search for any documentation or scripts that might generate these files
find doc-agents -type f \( -name "*.js" -o -name "*.ts" -o -name "*.py" -o -name "*.sh" -o -name "*.json" \) | grep -E "(gen|build|script)" | head -10Repository: agentuity/docs
Length of output: 388
🏁 Script executed:
# Let's search more carefully in the .agents directory
find doc-agents/.agents -name "SKILL.md" 2>/dev/null | wc -lRepository: agentuity/docs
Length of output: 60
🏁 Script executed:
# Count how many SKILL.md files have "unknown" type
find doc-agents/.agents -name "SKILL.md" -exec grep -l "unknown" {} \; 2>/dev/null | wc -lRepository: agentuity/docs
Length of output: 59
🏁 Script executed:
# Get total count of SKILL.md files in .agents
find doc-agents/.agents -name "SKILL.md" 2>/dev/null | wc -lRepository: agentuity/docs
Length of output: 60
🏁 Script executed:
# List a few other SKILL.md files to compare
find doc-agents/.agents -name "SKILL.md" 2>/dev/null | head -5 | xargs -I {} sh -c 'echo "File: {}" && tail -15 {}'Repository: agentuity/docs
Length of output: 1582
🏁 Script executed:
# List all SKILL.md files that have "unknown" types
find doc-agents/.agents -name "SKILL.md" -exec grep -l "unknown" {} \; 2>/dev/nullRepository: agentuity/docs
Length of output: 518
🏁 Script executed:
# Check if there's any auto-generation marker or comment pattern
find doc-agents/.agents -name "SKILL.md" -exec grep -l "unknown" {} \; | xargs head -5Repository: agentuity/docs
Length of output: 1887
🏁 Script executed:
# Compare the specific file against another one to see the pattern
echo "=== File WITH unknown ===" && \
sed -n '50,77p' doc-agents/.agents/skills/agentuity-cli-cloud-agent-get/SKILL.md && \
echo "" && echo "=== File WITHOUT unknown (auth-ssh-add) ===" && \
sed -n '50,77p' doc-agents/.agents/skills/agentuity-cli-auth-ssh-add/SKILL.mdRepository: agentuity/docs
Length of output: 1253
🏁 Script executed:
# Look for any README or documentation about schema generation
find doc-agents -type f \( -name "README*" -o -name "CONTRIBUTING*" \) | xargs grep -l "SKILL\|schema\|generate" 2>/dev/nullRepository: agentuity/docs
Length of output: 149
🏁 Script executed:
# Check the README files to understand the schema/auto-generation
cat doc-agents/.agents/skills/README.mdRepository: agentuity/docs
Length of output: 14078
🏁 Script executed:
# Also check the root README
cat doc-agents/README.md | head -50Repository: agentuity/docs
Length of output: 1511
🏁 Script executed:
# Look at one of the other files with "unknown" to understand the pattern
cat doc-agents/.agents/skills/agentuity-cli-cloud-deployment-show/SKILL.md | sed -n '50,77p'Repository: agentuity/docs
Length of output: 599
🏁 Script executed:
# Check if there's any TypeScript or code generation in the codebase
grep -r "unknown" doc-agents/src --include="*.ts" --include="*.js" 2>/dev/null | grep -i "type\|schema" | head -5Repository: agentuity/docs
Length of output: 40
🏁 Script executed:
# Verify line numbers are correct by checking exact line ranges
sed -n '50,77p' doc-agents/.agents/skills/agentuity-cli-cloud-agent-get/SKILL.md | wc -lRepository: agentuity/docs
Length of output: 60
🏁 Script executed:
# Check if there's documentation about what these "unknown" fields should actually contain
find doc-agents -type f \( -name "*.ts" -o -name "*.js" \) | xargs grep -l "deploymentId\|description.*unknown" 2>/dev/null | head -3Repository: agentuity/docs
Length of output: 40
These SKILL.md files are auto-generated; fix the upstream Agentuity CLI schema generator to provide complete type information.
The description, deploymentId, and metadata fields use the placeholder type "unknown" instead of actual types. This pattern appears in 7 SKILL.md files (agentuity-cli-cloud-agent-get, cloud-deployment-show, cloud-keyvalue-get, cloud-session-get, cloud-thread-get, profile-show, and project-show). Since these are auto-generated (per README: agentuity ai skills generate --output ./skills), the fix must be applied in the upstream Agentuity CLI's schema generation tooling, not here.
🤖 Prompt for AI Agents
In @doc-agents/.agents/skills/agentuity-cli-cloud-agent-get/SKILL.md around
lines 50 - 77, The generated SKILL.md contains placeholder types ("unknown") for
fields `description`, `deploymentId`, and `metadata` (e.g., in
agentuity-cli-cloud-agent-get SKILL.md); update the upstream Agentuity CLI
schema generator to map these schema properties to their real types (e.g.,
string/object/UUID/etc.) instead of emitting "unknown": locate the generator
logic that builds property type strings (the module invoked by the CLI command
`agentuity ai skills generate`) and add explicit handlers for `description`,
`deploymentId`, and `metadata` (or a generic rule that resolves unknown JSON
Schema/$ref types properly), then run the generator to regenerate all affected
SKILL.md files (cloud-deployment-show, cloud-keyvalue-get, cloud-session-get,
cloud-thread-get, profile-show, project-show) so the docs reflect correct types.
| ## Options | ||
|
|
||
| | Option | Type | Required | Default | Description | | ||
| |--------|------|----------|---------|-------------| | ||
| | `--name` | string | Yes | - | the name for the API key | | ||
| | `--expires-at` | string | Yes | - | expiration date as ISO 8601 (2025-12-31T23:59:59Z) or duration (1h, 2d, 30d, 1y) | | ||
| | `--confirm` | boolean | Yes | - | Skip confirmation prompts (required for non-TTY) | |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Clarify the --confirm parameter requirement.
The Options table marks --confirm as Required: Yes, but the description states "required for non-TTY" (conditional), and the first two examples omit it. This creates ambiguity about whether the parameter is universally required or only for non-interactive environments.
Reconcile the table, description, and examples to reflect the actual behavior. If --confirm is conditional, consider updating the table to clarify the condition or split the requirement.
| ## Examples | ||
|
|
||
| Execute SQL query: | ||
|
|
||
| ```bash | ||
| bunx @agentuity/cli cloud db sql my-database "SELECT * FROM users LIMIT 10" | ||
| ``` | ||
|
|
||
| Execute query with JSON output: | ||
|
|
||
| ```bash | ||
| bunx @agentuity/cli cloud db exec my-database "SELECT COUNT(*) FROM orders" --json | ||
| ``` | ||
|
|
||
| Query with filter: | ||
|
|
||
| ```bash | ||
| bunx @agentuity/cli cloud db query my-database "SELECT * FROM products WHERE price > 100" | ||
| ``` |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Fix example commands to match documented command syntax.
The documented command is agentuity cloud db sql (line 25), but examples 2 and 3 use different subcommands:
- Line 46:
cloud db exec(should becloud db sql) - Line 52:
cloud db query(should becloud db sql)
Only the first example (line 40) matches the documented syntax. This inconsistency could confuse users. Either update the examples to use sql or clarify if exec, query, and sql are aliases.
🔎 Proposed fix (if sql is the canonical command)
-Execute query with JSON output:
-
-```bash
-bunx @agentuity/cli cloud db exec my-database "SELECT COUNT(*) FROM orders" --json
-```
-
-Query with filter:
-
-```bash
-bunx @agentuity/cli cloud db query my-database "SELECT * FROM products WHERE price > 100"
+Execute query with JSON output:
+
+```bash
+bunx @agentuity/cli cloud db sql my-database "SELECT COUNT(*) FROM orders" --json
+```
+
+Query with filter:
+
+```bash
+bunx @agentuity/cli cloud db sql my-database "SELECT * FROM products WHERE price > 100"📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| ## Examples | |
| Execute SQL query: | |
| ```bash | |
| bunx @agentuity/cli cloud db sql my-database "SELECT * FROM users LIMIT 10" | |
| ``` | |
| Execute query with JSON output: | |
| ```bash | |
| bunx @agentuity/cli cloud db exec my-database "SELECT COUNT(*) FROM orders" --json | |
| ``` | |
| Query with filter: | |
| ```bash | |
| bunx @agentuity/cli cloud db query my-database "SELECT * FROM products WHERE price > 100" | |
| ``` | |
| ## Examples | |
| Execute SQL query: | |
🤖 Prompt for AI Agents
In @doc-agents/.agents/skills/agentuity-cli-cloud-db-sql/SKILL.md around lines
35 - 53, Examples 2 and 3 use the wrong subcommands ("cloud db exec" and "cloud
db query") and should match the documented canonical command "agentuity cloud db
sql"; update the example lines that currently show "bunx @agentuity/cli cloud db
exec my-database ..." and "bunx @agentuity/cli cloud db query my-database ..."
to use "bunx @agentuity/cli cloud db sql my-database ..." (including the --json
flag where present) so all examples consistently use the `sql` subcommand, or
alternatively add a note clarifying that `exec` and `query` are aliases of `sql`
if that is intended.
| ```bash | ||
| agentuity cloud env delete <key> | ||
| ``` | ||
|
|
||
| ## Arguments | ||
|
|
||
| | Argument | Type | Required | Description | | ||
| |----------|------|----------|-------------| | ||
| | `<key>` | string | Yes | - | | ||
|
|
||
| ## Examples | ||
|
|
||
| Delete item: | ||
|
|
||
| ```bash | ||
| bunx @agentuity/cli env delete OLD_FEATURE_FLAG | ||
| ``` | ||
|
|
||
| Delete item: | ||
|
|
||
| ```bash | ||
| bunx @agentuity/cli env rm PORT | ||
| ``` |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Examples use mismatched command syntax compared to documented usage.
The documented usage (line 25) shows agentuity cloud env delete <key>, but the examples use bunx @agentuity/cli env delete and bunx @agentuity/cli env rm. These are different command patterns. Align the examples with the documented usage, or clarify if these alternate syntaxes are intentional and documented elsewhere.
Additionally, both example descriptions ("Delete item:") are identical and non-descriptive. Provide more specific descriptions for each example.
🔎 Proposed fix for example consistency
## Examples
-Delete item:
+Delete an environment variable:
```bash
-bunx @agentuity/cli env delete OLD_FEATURE_FLAG
+agentuity cloud env delete OLD_FEATURE_FLAG-Delete item:
+Delete using the rm alias:
-bunx @agentuity/cli env rm PORT
+agentuity cloud env rm PORT</details>
<!-- suggestion_start -->
<details>
<summary>📝 Committable suggestion</summary>
> ‼️ **IMPORTANT**
> Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
```suggestion
🤖 Prompt for AI Agents
In @doc-agents/.agents/skills/agentuity-cli-cloud-env-delete/SKILL.md around
lines 24 - 46, The examples in SKILL.md use a different CLI invocation than the
documented usage; update the example commands to match the documented pattern
(use "agentuity cloud env delete <key>" and "agentuity cloud env rm <key>"
instead of "bunx @agentuity/cli ..."), and replace the two identical "Delete
item:" captions with specific descriptions—e.g., "Delete using full command:"
for the delete example and "Delete using the rm alias:" for the rm example—so
the examples align with the usage shown by the "agentuity cloud env delete"
heading.
| "@agentuity/cli": "latest", | ||
| "@types/bun": "latest", |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🛠️ Refactor suggestion | 🟠 Major
Pin devDependency versions instead of using "latest".
The same deterministic build concerns apply to devDependencies. Pin @agentuity/cli and @types/bun to specific versions.
📌 Suggested fix
"devDependencies": {
- "@agentuity/cli": "latest",
- "@types/bun": "latest",
+ "@agentuity/cli": "^0.0.111",
+ "@types/bun": "^1.0.0",
"@types/react": "^19.2.0",📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| "@agentuity/cli": "latest", | |
| "@types/bun": "latest", | |
| "@agentuity/cli": "^0.0.111", | |
| "@types/bun": "^1.0.0", |
🤖 Prompt for AI Agents
In @doc-agents/package.json around lines 29 - 30, The devDependencies in
package.json use floating "latest" versions for @agentuity/cli and @types/bun;
replace those with pinned, specific version strings (e.g., "1.2.3" style) to
ensure deterministic builds. Update the entries for "@agentuity/cli" and
"@types/bun" in package.json to concrete semver values (or exact versions) and
run npm/yarn install to regenerate lockfile so CI uses the pinned versions.
| export async function buildContext(ctx: any, tutorialState?: TutorialState): Promise<string> { | ||
| try { | ||
| const tutorials = await getTutorialList(ctx); | ||
|
|
||
| // Handle API failure early | ||
| if (!tutorials.success || !tutorials.data) { | ||
| ctx.logger.warn('Failed to load tutorial list'); | ||
| return defaultFallbackContext(); | ||
| } | ||
|
|
||
| const tutorialContent = JSON.stringify(tutorials.data, null, 2); | ||
| const currentTutorialInfo = buildCurrentTutorialInfo(tutorials.data, tutorialState); | ||
|
|
||
| return `===AVAILABLE TUTORIALS==== | ||
| ${tutorialContent} | ||
| ${currentTutorialInfo} | ||
| Note: You should not expose the details of the tutorial IDs to the user. | ||
| `; | ||
| } catch (error) { | ||
| ctx.logger.error('Error building tutorial context: %s', error); | ||
| return defaultFallbackContext(); | ||
| } | ||
| } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🧩 Analysis chain
🏁 Script executed:
# Find getTutorialList definition and its source
rg -n "getTutorialList" --type ts -g '!node_modules' -B 2 -A 10Repository: agentuity/docs
Length of output: 6102
🏁 Script executed:
# Search for Tutorial interface definition
rg -n "interface Tutorial\|type Tutorial" --type ts -g '!node_modules' -A 8Repository: agentuity/docs
Length of output: 40
🏁 Script executed:
# Check for any sanitization or validation functions related to tutorials
rg -n "sanitize|validate|escape" --type ts -g '!node_modules' -C 2Repository: agentuity/docs
Length of output: 6039
🏁 Script executed:
# Find where tutorials are created or loaded from
rg -n "tutorial" --type ts -g '!node_modules' -g '!*.test.ts' | head -30Repository: agentuity/docs
Length of output: 2347
🏁 Script executed:
# Get full getTutorialList implementation
sed -n '7,30p' doc-agents/src/agent/agent_pulse/tutorial.tsRepository: agentuity/docs
Length of output: 786
🏁 Script executed:
# Check if there's a Tutorial type definition with validation
rg -n "^(export )?type Tutorial|^(export )?interface Tutorial" --type ts -A 15 doc-agents/src/agent/agent_pulse/tutorial.tsRepository: agentuity/docs
Length of output: 40
🏁 Script executed:
# Check if there's any response validation or schema enforcement
rg -n "response.json()" doc-agents/src/agent/agent_pulse/tutorial.ts -A 10Repository: agentuity/docs
Length of output: 1561
🏁 Script executed:
# Check the rest of getTutorialList to see if data is validated
tail -n +30 doc-agents/src/agent/agent_pulse/tutorial.ts | head -20Repository: agentuity/docs
Length of output: 554
🏁 Script executed:
# Check if Tutorial type has any runtime validation (Zod, etc.)
rg -n "TutorialSchema|TutorialListSchema" --type tsRepository: agentuity/docs
Length of output: 374
🏁 Script executed:
# Look for the Tutorial type definition
rg -n "^export type Tutorial|^export interface Tutorial" --type ts doc-agents/src/agent/agent_pulse/Repository: agentuity/docs
Length of output: 207
🏁 Script executed:
# Get the full Tutorial interface definition
sed -n '11,25p' doc-agents/src/agent/agent_pulse/types.tsRepository: agentuity/docs
Length of output: 322
🏁 Script executed:
# Check if there's any runtime schema validation for Tutorial in tutorial.ts
cat doc-agents/src/agent/agent_pulse/tutorial.ts | head -50Repository: agentuity/docs
Length of output: 1440
Add runtime validation and sanitization for tutorial data from external API.
Line 33 in doc-agents/src/agent/agent_pulse/tutorial.ts receives tutorial data from an external API endpoint using only TypeScript type casting (as Tutorial[]), which provides no runtime validation. When this data is embedded directly into the system prompt via JSON.stringify (line 17 of context-builder.ts), fields like title, description, and difficulty could contain malicious content designed to manipulate the AI's behavior.
Implement runtime schema validation (e.g., Zod) when parsing the API response, and sanitize string fields before embedding them in the prompt context.
🤖 Prompt for AI Agents
In @doc-agents/src/agent/agent_pulse/context-builder.ts around lines 7 - 32, The
tutorial list returned by getTutorialList and embedded by buildContext is not
runtime-validated or sanitized; add a Zod schema for the Tutorial shape in the
module that parses the API response (the code that currently casts to `as
Tutorial[]` in tutorial.ts), validate the parsed payload and reject or coerce
invalid entries, then ensure buildContext uses the validated result (the value
returned by getTutorialList) and sanitizes all string fields (title,
description, difficulty, etc.) before embedding—e.g., trim, remove control/chars
that could inject prompts, and escape or redact suspicious tokens—so update
tutorial parsing to run Zod.parse/ safeParse and update buildContext (and
buildCurrentTutorialInfo if it formats fields) to call a small sanitizeString
helper on every string field prior to JSON.stringify or interpolation, falling
back to defaultFallbackContext on validation failure.
| function buildCurrentTutorialInfo(tutorials: Tutorial[], tutorialState?: TutorialState): string { | ||
| if (!tutorialState?.tutorialId) { | ||
| return ''; | ||
| } | ||
|
|
||
| const currentTutorial = tutorials.find((t) => t.id === tutorialState.tutorialId); | ||
| if (!currentTutorial) { | ||
| return '\nWarning: User appears to be in an unknown tutorial.'; | ||
| } | ||
| if (tutorialState.currentStep > currentTutorial.totalSteps) { | ||
| return `\nUser has completed the tutorial: ${currentTutorial.title} (${currentTutorial.totalSteps} steps)`; | ||
| } | ||
| return `\nUser is currently on this tutorial: ${currentTutorial.title} (Step ${tutorialState.currentStep} of ${currentTutorial.totalSteps})`; | ||
| } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🧩 Analysis chain
🏁 Script executed:
#!/bin/bash
# Search for currentStep usage and step advancement
rg -n "currentStep" --type ts --type tsx -C 3Repository: agentuity/docs
Length of output: 85
🏁 Script executed:
#!/bin/bash
# Search for TutorialState definition to understand step numbering
rg -n "interface TutorialState\|type TutorialState" --type ts --type tsx -A 10Repository: agentuity/docs
Length of output: 85
🏁 Script executed:
#!/bin/bash
# Look for tutorial completion logic or step progression elsewhere
rg -n "totalSteps\|tutorialId" --type ts --type tsx -C 2 | head -100Repository: agentuity/docs
Length of output: 85
🏁 Script executed:
#!/bin/bash
# Search for currentStep usage in TypeScript files
rg -n "currentStep" --type ts -C 3Repository: agentuity/docs
Length of output: 15277
🏁 Script executed:
#!/bin/bash
# Search for TutorialState definition
rg -n "TutorialState" --type ts -A 5 -B 2Repository: agentuity/docs
Length of output: 18436
🏁 Script executed:
#!/bin/bash
# Find the file location and check surrounding context
fd "context-builder" --type fRepository: agentuity/docs
Length of output: 109
Use >= for tutorial completion check to match state-manager logic.
Line 46 has an off-by-one inconsistency. In lib/tutorial/state-manager.ts (line 44), tutorials are marked completed when currentStep >= totalSteps. The context-builder should use the same condition for consistency—currently it only shows completion when currentStep > totalSteps, creating a mismatch where a tutorial is marked completed in state but not displayed as completed until currentStep exceeds totalSteps.
Change line 46 from:
if (tutorialState.currentStep > currentTutorial.totalSteps) {
to:
if (tutorialState.currentStep >= currentTutorial.totalSteps) {
🤖 Prompt for AI Agents
In @doc-agents/src/agent/agent_pulse/context-builder.ts around lines 37 - 50, In
buildCurrentTutorialInfo(tutorials: Tutorial[], tutorialState?: TutorialState)
adjust the completion check to match the state-manager by changing the condition
that uses tutorialState.currentStep vs currentTutorial.totalSteps from a strict
greater-than to greater-than-or-equal; specifically update the if in
buildCurrentTutorialInfo so it treats currentStep >= totalSteps as completed to
avoid the off-by-one mismatch with the state-manager logic.
| router.post('/', async (c) => { | ||
| try { | ||
| const body = await c.req.json(); | ||
| const conversationHistory = body.conversationHistory as ConversationMessage[]; | ||
|
|
||
| if (!conversationHistory || !Array.isArray(conversationHistory)) { | ||
| return c.json({ error: 'conversationHistory is required and must be an array' }, 400); | ||
| } | ||
|
|
||
| if (conversationHistory.length === 0) { | ||
| return c.json({ title: 'New chat' }); | ||
| } | ||
|
|
||
| const historyText = formatHistory(conversationHistory); | ||
| const prompt = `Generate a very short session title summarizing the conversation topic. | ||
| Requirements: | ||
| - sentence case | ||
| - no emojis | ||
| - <= 60 characters | ||
| - no quotes or markdown | ||
| - output the title only, no extra text | ||
| Conversation: | ||
| ${historyText}`; | ||
|
|
||
| const response = await generateText({ | ||
| model: openai('gpt-4o-mini'), | ||
| prompt, | ||
| system: | ||
| 'You are a title generator for chat sessions. Generate concise, descriptive titles only. Output only the title text, nothing else.', | ||
| }); | ||
|
|
||
| const title = sanitizeTitle(response.text); | ||
|
|
||
| return c.json({ | ||
| title: title || 'New chat', | ||
| }); | ||
| } catch (error) { | ||
| c.var.logger.error('Title generation failed: %s', error); | ||
| return c.json( | ||
| { | ||
| error: 'Failed to generate title', | ||
| details: error instanceof Error ? error.message : String(error), | ||
| }, | ||
| 500 | ||
| ); | ||
| } | ||
| }); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🧩 Analysis chain
🏁 Script executed:
#!/bin/bash
# Search for authentication middleware and bearer token usage in doc-agents routes
echo "=== Router middleware and auth setup in title-generator route ==="
rg -n "bearer|auth|middleware|router|post" --type=ts doc-agents/src/api/title-generator/ -C 5
echo -e "\n=== Check app-level middleware setup ==="
find doc-agents/src -name "*.ts" -type f | head -20 | xargs grep -l "middleware\|auth\|bearer" 2>/dev/null
echo -e "\n=== List all API route files ==="
fd -e ts "route" doc-agents/src/api/
echo -e "\n=== Check main app or router setup ==="
fd -e ts -path "*/api/*" doc-agents/src | head -20Repository: agentuity/docs
Length of output: 3219
🏁 Script executed:
#!/bin/bash
# Check other route files for authentication patterns
echo "=== Check other route files for auth patterns ==="
cat doc-agents/src/api/doc-qa/route.ts | head -80
echo -e "\n=== Check process-docs route ==="
cat doc-agents/src/api/process-docs/route.ts | head -80
echo -e "\n=== Search for auth/middleware keywords across doc-agents ==="
rg -n "auth|middleware|bearer|token" --type=ts doc-agents/src/
echo -e "\n=== Check for any app setup or index files ==="
fd -e ts "index|app|server|main" doc-agents/src/ | grep -v node_modules | head -20Repository: agentuity/docs
Length of output: 3673
🏁 Script executed:
#!/bin/bash
# Check agent_pulse route for auth and view auth middleware implementation
echo "=== Check agent_pulse route for auth ==="
head -20 doc-agents/src/api/agent_pulse/route.ts
echo -e "\n=== View bearerTokenAuth middleware ==="
cat doc-agents/src/middleware/auth.ts
echo -e "\n=== Check app.ts middleware application ==="
sed -n '50,100p' doc-agents/src/generated/app.tsRepository: agentuity/docs
Length of output: 3557
🏁 Script executed:
#!/bin/bash
# Check if agent_pulse route uses bearerTokenAuth
echo "=== Full agent_pulse route file ==="
wc -l doc-agents/src/api/agent_pulse/route.ts
echo -e "\n=== Check for auth in agent_pulse ==="
grep -n "bearerTokenAuth\|router.post" doc-agents/src/api/agent_pulse/route.ts | head -20Repository: agentuity/docs
Length of output: 192
🏁 Script executed:
#!/bin/bash
# Check the full router.post definition in agent_pulse
echo "=== Check agent_pulse router.post definition ==="
sed -n '43,50p' doc-agents/src/api/agent_pulse/route.tsRepository: agentuity/docs
Length of output: 287
🏁 Script executed:
#!/bin/bash
# Check for rate limiting in the codebase
echo "=== Search for rate limiting ==="
rg -n "rate|limit|throttle" --type=ts doc-agents/src/
echo -e "\n=== Check if there's rate limiting middleware ==="
fd -e ts "rate\|limit\|throttle" doc-agents/src/
echo -e "\n=== Check middleware directory ==="
ls -la doc-agents/src/middleware/Repository: agentuity/docs
Length of output: 4301
Add bearer token authentication middleware to this endpoint.
This POST handler lacks authentication and makes direct calls to the OpenAI API, exposing the application to unauthorized access and cost abuse. The bearerTokenAuth middleware already exists in the codebase and is applied to similar endpoints (e.g., doc-qa), but is missing here.
Add the import and middleware:
import { bearerTokenAuth } from '@middleware/auth';
router.post('/', bearerTokenAuth, async (c) => {
Additionally, rate limiting is not currently implemented in the codebase. Consider adding rate limiting middleware for all OpenAI API endpoints to protect against abuse.
🤖 Prompt for AI Agents
In @doc-agents/src/api/title-generator/route.ts around lines 54 - 102, The POST
handler at router.post('/') is missing authentication; import the existing
bearerTokenAuth (symbol: bearerTokenAuth) and apply it as middleware on the
route (i.e., router.post('/', bearerTokenAuth, async (c) => ...) so the request
is authenticated before calling generateText/openai; update the file imports to
include bearerTokenAuth and ensure the route signature still uses the async
handler (router.post). Also add or wire a rate-limiting middleware (e.g., a
shared rateLimit middleware used across OpenAI endpoints) to this route to
protect against abuse.
| interface AgentQaResponse { | ||
| answer: string; | ||
| documents?: string[]; | ||
| } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🛠️ Refactor suggestion | 🟠 Major
Export AgentQaResponse for external usage.
The AgentQaResponse interface is re-exported in lib/api/services/index.ts (lines 11), indicating it's part of the public API surface. It should be exported from this file.
🔎 Proposed fix
-interface AgentQaResponse {
+export interface AgentQaResponse {
answer: string;
documents?: string[];
}🤖 Prompt for AI Agents
In @lib/api/services/agentQa.ts around lines 12 - 15, The AgentQaResponse
interface is currently not exported but is intended for public use; modify the
declaration of AgentQaResponse in agentQa.ts so it is exported (e.g., add the
export keyword before the interface or export it as a type alias) so the symbol
AgentQaResponse is available for the existing re-export in
lib/api/services/index.ts.
- Added new environment variables: AGENT_BEARER_TOKEN and AGENTUITY_REGION to .env.example for improved configuration. - Updated KV service initialization to require AGENTUITY_REGION alongside AGENTUITY_SDK_KEY for better error handling. - Refactored logger implementation to utilize createLogger from the agentuity server package for improved logging capabilities.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 3
🤖 Fix all issues with AI agents
In @lib/kv-store.ts:
- Around line 34-48: initializeKVService() currently constructs a new
KeyValueStorageService and adapter on every call, causing unnecessary allocation
and overhead; change it to lazily cache the service instance in module scope
(e.g., a private variable) and return that cached instance on subsequent calls
so adapter and KeyValueStorageService are created only once; update
initializeKVService (or provide a new getKVService wrapper) to perform the
one-time creation using the existing createServerFetchAdapter, getServiceUrls,
and KeyValueStorageService logic and then return the cached instance for all
callers (ensure the env checks remain on first init).
- Around line 125-128: The deleteKVValue function currently returns
Promise<boolean> while a KVDeleteResult interface exists; update deleteKVValue
to return Promise<KVDeleteResult> with shape {deleted: boolean, error?: string}
(mirroring getKVValue's KVGetResult pattern) so callers can distinguish "not
found" vs "error", adjust catch to populate error and deleted=false, and update
any callers accordingly; also consider making setKVValue follow the same pattern
(Promise<KVDeleteResult>-style result or a KVSetResult) for consistency with
getKVValue and to surface error details from setKVValue.
- Around line 70-75: The catch block that currently logs the error and returns {
exists: false } (catch(error) { console.error(...); return { exists: false }; })
masks service errors as “key not found”; change the error handling in the KV
access function so it no longer conflates failures with missing keys—either
rethrow the caught error (propagate the exception) or return a richer result
shape (e.g., include an error string or code like { exists?: boolean; error?:
string }) so callers such as the [sessionId]/route.ts handler can distinguish
404 from 5xx and handle/translate errors appropriately; ensure you update the
function signature and any callers to handle the new behavior.
🧹 Nitpick comments (1)
lib/kv-store.ts (1)
27-29: Remove unusedKVDeleteResultinterface.The
KVDeleteResultinterface is defined but never used. ThedeleteKVValuefunction returnsPromise<boolean>instead (line 118). Consider either removing this unused type or updatingdeleteKVValueto returnKVDeleteResultfor consistency withKVGetResult.♻️ Proposed fix: Remove unused interface
-export interface KVDeleteResult { - exists: boolean; -} -
📜 Review details
Configuration used: Organization UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (2)
.env.examplelib/kv-store.ts
🧰 Additional context used
🧬 Code graph analysis (1)
lib/kv-store.ts (1)
lib/config.ts (1)
config(6-10)
🪛 dotenv-linter (4.0.0)
.env.example
[warning] 7-7: [EndingBlankLine] No blank line at the end of the file
(EndingBlankLine)
[warning] 7-7: [UnorderedKey] The AGENTUITY_REGION key should go before the AGENTUITY_SDK_KEY key
(UnorderedKey)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (1)
- GitHub Check: sync
🔇 Additional comments (5)
.env.example (2)
5-7: Fix formatting and key ordering per linter.Two static analysis issues detected:
- Missing blank line at end of file (line 7)
- Key ordering:
AGENTUITY_REGIONshould precedeAGENTUITY_SDK_KEY📋 Proposed fix
-AGENTUITY_SDK_KEY= -AGENT_BEARER_TOKEN= -AGENTUITY_REGION=use +AGENTUITY_REGION=use +AGENTUITY_SDK_KEY= +AGENT_BEARER_TOKEN=[suggest_minor_issue]
5-7: Update README.md to reference AGENTUITY_SDK_KEY instead of AGENTUITY_API_KEY.The README.md file (lines 37-38) still instructs users to update
AGENTUITY_API_KEY, which contradicts the .env.example file that now uses onlyAGENTUITY_SDK_KEY. Additionally, whileagent-docs/index.tsmaintains backward compatibility by accepting both keys, the README should be updated to align with the new key name to avoid confusion.lib/kv-store.ts (3)
1-11: LGTM! Clear documentation and appropriate imports.The file header clearly documents the server-side-only restriction and the imports are appropriate for the SDK-based approach.
93-96: Good: TTL validation enforces minimum threshold.The TTL validation correctly enforces a minimum of 60 seconds and throws an error immediately, preventing invalid configurations from reaching the KV service.
103-106: Verify silent error handling is intentional.The
setKVValuefunction catches all errors and returns a boolean, making it impossible for callers to distinguish between different failure scenarios (authentication failures, quota issues, invalid store names, network errors, etc.). Most callers do capture the return value, but without granular error information, they can only know that an operation failed, not why. Additionally, at least one caller (lib/tutorial/state-manager.ts:98incompleteTutorial()) ignores the return value entirely, swallowing errors silently. Consider whether the function should either throw specific error types or return a result object that includes error details (similar to howgetKVValuereturnsKVGetResultwithexists/data, but improved to include error context).
| // Initialize the KV service | ||
| function initializeKVService() { | ||
| if (!process.env.AGENTUITY_SDK_KEY || !process.env.AGENTUITY_REGION) { | ||
| throw new Error('AGENTUITY_SDK_KEY and AGENTUITY_REGION environment variables are required'); | ||
| } | ||
|
|
||
| return null; | ||
| const adapter = createServerFetchAdapter({ | ||
| headers: { | ||
| Authorization: `Bearer ${process.env.AGENTUITY_SDK_KEY}` | ||
| }, | ||
| }, logger); | ||
|
|
||
| const serviceUrls = getServiceUrls(process.env.AGENTUITY_REGION); | ||
| return new KeyValueStorageService(serviceUrls.keyvalue, adapter); | ||
| } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🛠️ Refactor suggestion | 🟠 Major
Service instance created on every operation causes performance overhead.
initializeKVService() is called on every KV operation (lines 63, 99, 122), creating a new KeyValueStorageService instance each time. This introduces unnecessary overhead for service initialization, adapter creation, and object allocation.
Consider caching the service instance with lazy initialization:
♻️ Proposed refactor: Cache service instance
+// Cache the KV service instance
+let kvServiceInstance: KeyValueStorageService | null = null;
+
// Initialize the KV service
function initializeKVService() {
+ if (kvServiceInstance) {
+ return kvServiceInstance;
+ }
+
if (!process.env.AGENTUITY_SDK_KEY || !process.env.AGENTUITY_REGION) {
throw new Error('AGENTUITY_SDK_KEY and AGENTUITY_REGION environment variables are required');
}
const adapter = createServerFetchAdapter({
headers: {
Authorization: `Bearer ${process.env.AGENTUITY_SDK_KEY}`
},
}, logger);
const serviceUrls = getServiceUrls(process.env.AGENTUITY_REGION);
- return new KeyValueStorageService(serviceUrls.keyvalue, adapter);
+ kvServiceInstance = new KeyValueStorageService(serviceUrls.keyvalue, adapter);
+ return kvServiceInstance;
}📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| // Initialize the KV service | |
| function initializeKVService() { | |
| if (!process.env.AGENTUITY_SDK_KEY || !process.env.AGENTUITY_REGION) { | |
| throw new Error('AGENTUITY_SDK_KEY and AGENTUITY_REGION environment variables are required'); | |
| } | |
| return null; | |
| const adapter = createServerFetchAdapter({ | |
| headers: { | |
| Authorization: `Bearer ${process.env.AGENTUITY_SDK_KEY}` | |
| }, | |
| }, logger); | |
| const serviceUrls = getServiceUrls(process.env.AGENTUITY_REGION); | |
| return new KeyValueStorageService(serviceUrls.keyvalue, adapter); | |
| } | |
| // Cache the KV service instance | |
| let kvServiceInstance: KeyValueStorageService | null = null; | |
| // Initialize the KV service | |
| function initializeKVService() { | |
| if (kvServiceInstance) { | |
| return kvServiceInstance; | |
| } | |
| if (!process.env.AGENTUITY_SDK_KEY || !process.env.AGENTUITY_REGION) { | |
| throw new Error('AGENTUITY_SDK_KEY and AGENTUITY_REGION environment variables are required'); | |
| } | |
| const adapter = createServerFetchAdapter({ | |
| headers: { | |
| Authorization: `Bearer ${process.env.AGENTUITY_SDK_KEY}` | |
| }, | |
| }, logger); | |
| const serviceUrls = getServiceUrls(process.env.AGENTUITY_REGION); | |
| kvServiceInstance = new KeyValueStorageService(serviceUrls.keyvalue, adapter); | |
| return kvServiceInstance; | |
| } |
🤖 Prompt for AI Agents
In @lib/kv-store.ts around lines 34 - 48, initializeKVService() currently
constructs a new KeyValueStorageService and adapter on every call, causing
unnecessary allocation and overhead; change it to lazily cache the service
instance in module scope (e.g., a private variable) and return that cached
instance on subsequent calls so adapter and KeyValueStorageService are created
only once; update initializeKVService (or provide a new getKVService wrapper) to
perform the one-time creation using the existing createServerFetchAdapter,
getServiceUrls, and KeyValueStorageService logic and then return the cached
instance for all callers (ensure the env checks remain on first init).
| } catch (error) { | ||
| console.error(`Failed to get KV value for key '${key}':`, error); | ||
| return { | ||
| success: false, | ||
| error: error instanceof Error ? error.message : 'Unknown error occurred' | ||
| exists: false | ||
| }; | ||
| } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🧩 Analysis chain
🏁 Script executed:
rg -nP --type=ts -C3 'await\s+getKVValue\s*\('Repository: agentuity/docs
Length of output: 40
🏁 Script executed:
rg -nP --type=ts 'getKVValue'Repository: agentuity/docs
Length of output: 1990
🏁 Script executed:
cat -n app/api/sessions/route.ts | head -50Repository: agentuity/docs
Length of output: 2528
🏁 Script executed:
cat -n app/api/sessions/[sessionId]/route.ts | head -50Repository: agentuity/docs
Length of output: 1996
🏁 Script executed:
cat -n lib/kv-store.tsRepository: agentuity/docs
Length of output: 4334
Reconsider error handling strategy to distinguish between missing data and service errors.
All errors are silently caught and logged to console, with exists: false returned regardless of error type. This masks critical failures (network issues, auth failures, missing environment variables) as missing data. Callers treat exists: false as "key doesn't exist" — for example, [sessionId]/route.ts returns a 404 when the actual issue may be a service error that should return 5xx.
This pattern prevents callers from:
- Returning appropriate HTTP status codes (distinguishing 404 from 500)
- Implementing error-specific handling logic
- Properly diagnosing production issues beyond console logs
Consider either propagating errors or returning a richer result type (e.g., { exists?: boolean; error?: string }) so callers can handle different failure modes appropriately.
🤖 Prompt for AI Agents
In @lib/kv-store.ts around lines 70 - 75, The catch block that currently logs
the error and returns { exists: false } (catch(error) { console.error(...);
return { exists: false }; }) masks service errors as “key not found”; change the
error handling in the KV access function so it no longer conflates failures with
missing keys—either rethrow the caught error (propagate the exception) or return
a richer result shape (e.g., include an error string or code like { exists?:
boolean; error?: string }) so callers such as the [sessionId]/route.ts handler
can distinguish 404 from 5xx and handle/translate errors appropriately; ensure
you update the function signature and any callers to handle the new behavior.
| } catch (error) { | ||
| return { | ||
| success: false, | ||
| error: error instanceof Error ? error.message : 'Unknown error occurred' | ||
| }; | ||
| } | ||
| } | ||
|
|
||
| /** | ||
| * Search for keys in the KV store by keyword pattern | ||
| * @param keyword - The keyword pattern to search for | ||
| * @param options - Optional configuration | ||
| * @returns Promise<KVStoreResponse<Array<{key: string, value: any, metadata?: any}>>> | ||
| */ | ||
| export async function searchKVByKeyword<T = any>( | ||
| keyword: string, | ||
| options: KVStoreOptions = {} | ||
| ): Promise<KVStoreResponse<Array<{key: string, value: T, metadata?: any}>>> { | ||
| const { storeName } = options; | ||
| const finalStoreName = storeName || config.defaultStoreName; | ||
|
|
||
| // Validate API key | ||
| if (!process.env.AGENTUITY_API_KEY) { | ||
| return { | ||
| success: false, | ||
| error: 'AGENTUITY_API_KEY environment variable is required' | ||
| }; | ||
| } | ||
|
|
||
| try { | ||
| const url = `${config.baseUrl}/sdk/kv/search/${encodeURIComponent(finalStoreName)}/${encodeURIComponent(keyword)}`; | ||
|
|
||
| const response = await fetch(url, { | ||
| method: 'GET', | ||
| headers: { | ||
| 'Authorization': `Bearer ${process.env.AGENTUITY_API_KEY}`, | ||
| 'Content-Type': 'application/json', | ||
| 'User-Agent': 'Next.js KV Client' | ||
| } | ||
| }); | ||
|
|
||
| if (!response.ok) { | ||
| const errorText = await response.text(); | ||
| return { | ||
| success: false, | ||
| error: `HTTP ${response.status}: ${errorText}`, | ||
| statusCode: response.status | ||
| }; | ||
| } | ||
|
|
||
| const data = await response.text(); | ||
|
|
||
| try { | ||
| const jsonData = JSON.parse(data); | ||
| return { | ||
| success: true, | ||
| data: jsonData, | ||
| statusCode: response.status | ||
| }; | ||
| } catch (parseError) { | ||
| return { | ||
| success: false, | ||
| error: 'Failed to parse search results as JSON', | ||
| statusCode: response.status | ||
| }; | ||
| } | ||
|
|
||
| } catch (error) { | ||
| return { | ||
| success: false, | ||
| error: error instanceof Error ? error.message : 'Unknown error occurred' | ||
| }; | ||
| console.error(`Failed to delete KV value for key '${key}':`, error); | ||
| return false; | ||
| } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🧩 Analysis chain
🏁 Script executed:
cat -n lib/kv-store.ts | head -150Repository: agentuity/docs
Length of output: 4334
🏁 Script executed:
rg -nP --type=ts -C3 'await\s+deleteKVValue\s*\('Repository: agentuity/docs
Length of output: 594
🏁 Script executed:
cat -n app/api/sessions/[sessionId]/route.ts | sed -n '140,160p'Repository: agentuity/docs
Length of output: 869
🏁 Script executed:
rg -nP --type=ts 'await\s+(deleteKVValue|setKVValue|getKVValue)\s*\(' --max-count=20Repository: agentuity/docs
Length of output: 1429
🏁 Script executed:
cat -n app/api/sessions/[sessionId]/messages/route.ts | sed -n '80,85p; 98,105p; 196,205p'Repository: agentuity/docs
Length of output: 1100
Consider returning KVDeleteResult from deleteKVValue for consistency with getKVValue.
The KVDeleteResult interface is defined (lines 27-29) but unused. getKVValue returns KVGetResult<T> with {exists: boolean, data?: T}, allowing callers to distinguish between "not found" and "error" states. For consistency, deleteKVValue should return Promise<KVDeleteResult> instead of Promise<boolean>. Note that setKVValue has the same issue—consider whether it should also return a result object rather than a simple boolean.
The error handling pattern (catch, log, return false) is intentional and working as designed—callers like the session deletion endpoint properly check the return value and respond with appropriate HTTP errors.
🤖 Prompt for AI Agents
In @lib/kv-store.ts around lines 125 - 128, The deleteKVValue function currently
returns Promise<boolean> while a KVDeleteResult interface exists; update
deleteKVValue to return Promise<KVDeleteResult> with shape {deleted: boolean,
error?: string} (mirroring getKVValue's KVGetResult pattern) so callers can
distinguish "not found" vs "error", adjust catch to populate error and
deleted=false, and update any callers accordingly; also consider making
setKVValue follow the same pattern (Promise<KVDeleteResult>-style result or a
KVSetResult) for consistency with getKVValue and to surface error details from
setKVValue.
- Updated the agent pulse API to streamline message handling and response streaming. - Introduced a new state manager to handle tutorial actions and fetch complete tutorial step data. - Refactored the streaming processor to format AI responses as SSE-compatible chunks. - Improved error handling and logging throughout the agent pulse services. - Added tutorial data handling to provide users with relevant content during interactions.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 7
🤖 Fix all issues with AI agents
In @app/api/sessions/[sessionId]/messages/route.ts:
- Around line 169-185: The async onTutorialData handler can throw and is invoked
without awaiting in callAgentPulseStreaming, risking unhandled rejections;
modify the invocation to await callbacks.onTutorialData?.(data) or wrap the
handler body in a try-catch so TutorialStateManager.updateTutorialProgress
errors are caught and logged before calling controller.enqueue/encoder.encode,
ensuring any thrown error is handled and does not become an unhandled promise
rejection.
In @doc-agents/src/agent/agent_pulse/context-builder.ts:
- Around line 85-86: The system prompt rule incorrectly references
startTutorialById; update the prompt text to reference the actual tool name
startTutorialAtStep (used in tools.ts and around lines 80-81) and adjust the
rule wording so it instructs using startTutorialAtStep only when the user
selects a tutorial, defaulting the step to 1 for new tutorials and validating
that the step is between 1 and the tutorial's totalSteps.
In @doc-agents/src/agent/agent_pulse/streaming-processor.ts:
- Around line 74-75: The call site for handleTutorialState in
streaming-processor.ts passes logger directly but handleTutorialState expects a
ctx object with a logger property (it calls ctx.logger.info, etc.); fix by
passing an object containing the logger (e.g., { logger }) or the existing ctx
object instead of the bare logger so the parameter shape matches
handleTutorialState, and update any other nearby calls to handleTutorialState to
use the same ctx-shaped argument.
- Around line 9-13: The function signature uses StreamTextResult<> with an empty
type parameter which is a parse/TS error; update the signature in
createStreamingProcessor to supply an appropriate generic (e.g.,
StreamTextResult<string> or StreamTextResult<any> / StreamTextResult<unknown>
depending on expected payload) and adjust any callers or imports accordingly so
the generic is consistent across usages (ensure the import/definition of
StreamTextResult supports the chosen type).
In @doc-agents/src/agent/agent_pulse/tutorial.ts:
- Around line 124-135: The interface TutorialStepResponseData is declared but
not exported, yet it's used as the public return type of getTutorialStep; make
it available to consumers by adding an export to the declaration (export
interface TutorialStepResponseData) so external callers can import the type, and
ensure any related exports/barrel files that should re-export it include this
symbol if necessary; update references to import the exported
TutorialStepResponseData where used.
In @lib/api/services/agentPulse.ts:
- Around line 124-136: The final SSE buffer parsing only handles text-delta and
finish types; update the try block that parses StreamingChunk from buffer (the
buffer variable and JSON.parse(buffer.slice(6))) to also handle other chunk
types consistently by invoking the corresponding callbacks on the callbacks
object: call callbacks.onStatus for type === 'status', callbacks.onTutorialData
for type === 'tutorial-data' and callbacks.onError for type === 'error'
(preserving the existing callbacks.onTextDelta and callbacks.onFinish handling),
and add a default branch to log or ignore unknown chunk.type values; keep the
surrounding try/catch intact to report parse errors.
🧹 Nitpick comments (13)
app/api/sessions/[sessionId]/messages/route.ts (1)
14-16: Unused constantAGENT_REQUEST_TIMEOUT.The
AGENT_REQUEST_TIMEOUTconstant is defined but never used in this file. The timeout is now handled withincallAgentPulseStreaming(which usesAGENT_PULSE_TIMEOUT= 30000ms internally).🧹 Remove unused constant
// Constants const DEFAULT_CONVERSATION_HISTORY_LIMIT = 10; -const AGENT_REQUEST_TIMEOUT = 30000; // 30 secondsdoc-agents/src/api/agent_pulse/route.ts (2)
14-38: Potential code duplication with existing parser.This
parseAgentRequestfunction appears to duplicate logic fromagent-docs/src/agents/agent-pulse/request/parser.ts. Consider extracting to a shared utility to maintain consistency.Additionally, the author field cast on line 24 may produce invalid values (e.g.,
'SYSTEM'.toUpperCase()yields'SYSTEM'which doesn't match'USER' | 'ASSISTANT').🔧 Suggested type-safe normalization
conversationHistory = body.conversationHistory.map((msg: any) => ({ - author: (msg.author || msg.role || 'USER').toUpperCase(), + author: ((msg.author || msg.role || 'USER').toUpperCase() === 'ASSISTANT' ? 'ASSISTANT' : 'USER') as 'USER' | 'ASSISTANT', content: msg.content || '', }));
73-86: Fragile error status code determination.Using
error.message.includes('Invalid')to distinguish 400 vs 500 errors is brittle. Consider using a custom error class or error codes for more reliable classification.// Example: Define a ValidationError class class ValidationError extends Error { constructor(message: string) { super(message); this.name = 'ValidationError'; } } // Then in catch block: const statusCode = error instanceof ValidationError ? 400 : 500;doc-agents/src/agent/agent_pulse/state-manager.ts (2)
40-46: Remove unnecessaryelseclause.As indicated by static analysis, the
elseblock is unnecessary because theifbranch at line 26 ends withreturn(implicitly viabreakfollowed byreturn null). The code afterif (tutorialStep.success && tutorialStep.data)can be flattened.🧹 Suggested fix
if (tutorialStep.success && tutorialStep.data) { const tutorialData: TutorialData = { tutorialId: action.tutorialId, totalSteps: action.totalSteps, currentStep: action.currentStep, tutorialStep: { title: tutorialStep.data.tutorialStep.title, mdx: tutorialStep.data.tutorialStep.mdx, snippets: tutorialStep.data.tutorialStep.snippets, totalSteps: tutorialStep.data.tutorialStep.totalSteps, }, }; ctx.logger.info('Tutorial state processed successfully'); return tutorialData; - } else { - // Handle API errors gracefully - ctx.logger.error('Failed to fetch tutorial step: %s', tutorialStep.error || 'Unknown error'); - if (tutorialStep.details) { - ctx.logger.error('Error details: %s', JSON.stringify(tutorialStep.details)); - } } + // Handle API errors gracefully + ctx.logger.error('Failed to fetch tutorial step: %s', tutorialStep.error || 'Unknown error'); + if (tutorialStep.details) { + ctx.logger.error('Error details: %s', JSON.stringify(tutorialStep.details)); + } } break;
54-60: Consider returningnullinstead of re-throwing.Re-throwing the error may cause unhandled promise rejections in the streaming context (the caller in
streaming-processor.tswraps this in try-catch, but returningnullwould be more consistent with the function's return signature and error handling pattern).🛡️ Suggested change
} catch (error) { ctx.logger.error( 'Failed to handle tutorial state: %s', error instanceof Error ? error.message : String(error) ); - throw error; + return null; }doc-agents/src/agent/agent_pulse/context-builder.ts (1)
1-2: Unused importgetTutorialMeta.
getTutorialMetais imported but not used in this file.🧹 Remove unused import
-import { getTutorialList, getTutorialMeta, type Tutorial } from './tutorial'; +import { getTutorialList, type Tutorial } from './tutorial';lib/api/services/agentPulse.ts (2)
8-16: Type duplication with doc-agents package.
ConversationMessageandTutorialStateinterfaces duplicate definitions fromdoc-agents/src/agent/agent_pulse/types.ts. Consider sharing types via a common package or re-exporting to ensure consistency.
34-40: Async callbacks are not awaited.The callbacks in
AgentPulseCallbacksmay be async (as used in the messages route), butcallAgentPulseStreaminginvokes them withoutawait. This means any async work in callbacks becomes fire-and-forget, and errors become unhandled rejections.Consider either:
- Documenting that callbacks must be synchronous
- Awaiting callbacks (requires making them
Promise<void>typed)🔧 Option: Await callbacks
export interface AgentPulseCallbacks { - onTextDelta?: (text: string) => void; - onStatus?: (message: string, category?: string) => void; - onTutorialData?: (data: any) => void; - onFinish?: () => void; - onError?: (error: string) => void; + onTextDelta?: (text: string) => void | Promise<void>; + onStatus?: (message: string, category?: string) => void | Promise<void>; + onTutorialData?: (data: any) => void | Promise<void>; + onFinish?: () => void | Promise<void>; + onError?: (error: string) => void | Promise<void>; }Then in the processing loop:
- callbacks.onTextDelta?.(chunk.textDelta); + await callbacks.onTextDelta?.(chunk.textDelta);doc-agents/src/agent/agent_pulse/tutorial.ts (3)
1-5: Circular dependency betweentutorial.tsandtypes.ts.This file imports from
./types, whiletypes.tsimportsTutorialSnippetfrom this file. This circular dependency can cause issues with some bundlers and module resolution. Consider movingTutorialSnippettotypes.tsalongside the other shared types to break the cycle.
7-47: Consider adding request timeout for reliability.The
fetchcall has no timeout, which could cause requests to hang indefinitely if the Tutorial API is unresponsive. Consider usingAbortControllerwith a timeout.Example with timeout
const controller = new AbortController(); const timeout = setTimeout(() => controller.abort(), 10000); // 10s timeout try { const response = await fetch(`${TUTORIAL_API_BASE_URL}/api/tutorials`, { signal: controller.signal }); // ... rest of logic } finally { clearTimeout(timeout); }
59-59: Consider encodingtutorialIdin URL path.If
tutorialIdcould contain special characters (e.g.,/,?,#), the URL would be malformed. UseencodeURIComponentfor safety.- const response = await fetch(`${TUTORIAL_API_BASE_URL}/api/tutorials/${tutorialId}`); + const response = await fetch(`${TUTORIAL_API_BASE_URL}/api/tutorials/${encodeURIComponent(tutorialId)}`);doc-agents/src/agent/agent_pulse/types.ts (2)
1-1: Circular import creates potential bundling issues.Importing
TutorialSnippetfrom./tutorialwhiletutorial.tsimports from this file creates a circular dependency. Consider definingTutorialSnippetin this types file to centralize all shared types and break the cycle.
41-52: Note:totalStepsappears at two levels.Both
TutorialData.totalStepsandTutorialData.tutorialStep.totalStepsexist. If this duplication is intentional to match the frontend's expected format, consider adding a comment clarifying they should always be in sync, or document why both are needed.
📜 Review details
Configuration used: Organization UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (10)
app/api/sessions/[sessionId]/messages/route.tsdoc-agents/src/agent/agent_pulse/agent.tsdoc-agents/src/agent/agent_pulse/context-builder.tsdoc-agents/src/agent/agent_pulse/state-manager.tsdoc-agents/src/agent/agent_pulse/streaming-processor.tsdoc-agents/src/agent/agent_pulse/tutorial.tsdoc-agents/src/agent/agent_pulse/types.tsdoc-agents/src/api/agent_pulse/route.tslib/api/services/agentPulse.tslib/api/services/index.ts
🚧 Files skipped from review as they are similar to previous changes (1)
- lib/api/services/index.ts
🧰 Additional context used
🧬 Code graph analysis (8)
doc-agents/src/api/agent_pulse/route.ts (2)
doc-agents/src/agent/agent_pulse/types.ts (1)
ConversationMessage(3-6)agent-docs/src/agents/agent-pulse/request/parser.ts (1)
parseAgentRequest(4-46)
doc-agents/src/agent/agent_pulse/agent.ts (4)
doc-agents/src/agent/agent_pulse/types.ts (2)
Action(34-39)ConversationMessage(3-6)doc-agents/src/agent/agent_pulse/tools.ts (1)
createTools(15-78)doc-agents/src/agent/agent_pulse/context-builder.ts (2)
buildContext(7-32)buildSystemPrompt(63-118)doc-agents/src/agent/agent_pulse/streaming-processor.ts (1)
createStreamingProcessor(9-109)
doc-agents/src/agent/agent_pulse/state-manager.ts (3)
doc-agents/src/agent/agent_pulse/types.ts (2)
Action(34-39)TutorialData(42-52)agent-docs/src/agents/agent-pulse/state.ts (1)
ActionType(46-46)doc-agents/src/agent/agent_pulse/tutorial.ts (1)
getTutorialStep(137-190)
lib/api/services/agentPulse.ts (3)
doc-agents/src/agent/agent_pulse/types.ts (3)
ConversationMessage(3-6)TutorialState(8-11)StreamingChunk(54-62)lib/api/services/index.ts (5)
AgentPulseRequest(9-9)StreamingChunk(9-9)AgentPulseCallbacks(9-9)callAgentPulseStreaming(8-8)agentPulseService(8-8)lib/config.ts (1)
config(6-10)
doc-agents/src/agent/agent_pulse/context-builder.ts (2)
doc-agents/src/agent/agent_pulse/types.ts (2)
TutorialState(8-11)Tutorial(13-20)doc-agents/src/agent/agent_pulse/tutorial.ts (2)
getTutorialList(7-47)Tutorial(3-3)
doc-agents/src/agent/agent_pulse/types.ts (2)
doc-agents/src/agent/agent_pulse/tutorial.ts (2)
Tutorial(3-3)TutorialSnippet(115-122)lib/api/services/agentPulse.ts (1)
StreamingChunk(24-32)
doc-agents/src/agent/agent_pulse/tutorial.ts (1)
doc-agents/src/agent/agent_pulse/types.ts (2)
ApiResponse(22-28)Tutorial(13-20)
app/api/sessions/[sessionId]/messages/route.ts (7)
lib/config.ts (1)
config(6-10)app/chat/types.ts (3)
Session(54-54)TutorialData(27-27)Message(37-37)lib/api/services/index.ts (2)
titleGeneratorService(6-6)callAgentPulseStreaming(8-8)lib/api/services/titleGenerator.ts (1)
titleGeneratorService(42-44)lib/kv-store.ts (2)
getKVValue(56-76)setKVValue(85-107)lib/api/services/agentPulse.ts (1)
callAgentPulseStreaming(48-145)app/chat/utils/dateUtils.ts (1)
getCurrentTimestamp(35-37)
🪛 Biome (2.1.2)
doc-agents/src/agent/agent_pulse/streaming-processor.ts
[error] 10-10: Expected a type parameter but instead found '>'.
Expected a type parameter here.
(parse)
doc-agents/src/agent/agent_pulse/state-manager.ts
[error] 40-46: This else clause can be omitted because previous branches break early.
Safe fix: Omit the else clause.
(lint/style/noUselessElse)
🔇 Additional comments (18)
app/api/sessions/[sessionId]/messages/route.ts (2)
57-88: LGTM - Background title generation is well-designed.The function properly handles race conditions by re-fetching the session before updating, includes appropriate null checks, and uses fire-and-forget pattern (
void) at the call site. Error handling is in place.
248-254: LGTM - SSE response setup is correct.Proper headers for server-sent events:
Content-Type: text/event-stream,Cache-Control: no-cache, andConnection: keep-alive.doc-agents/src/api/agent_pulse/route.ts (1)
58-72: LGTM - Streaming response setup.The agent invocation and SSE response headers are correctly configured.
doc-agents/src/agent/agent_pulse/agent.ts (3)
10-31: LGTM - Agent schema definition.Input schema is well-structured with proper optional fields and descriptions. Using
s.any()for output is acceptable since the handler returns aReadableStream.
63-74: LGTM - Logging callbacks for debugging.The
onStepFinishandonFinishcallbacks provide comprehensive debugging information for the streaming flow.
55-56: No action needed. The modelgpt-4.1is a valid OpenAI model name (launched April 14, 2025) and will not cause runtime errors.Likely an incorrect or invalid review comment.
doc-agents/src/agent/agent_pulse/state-manager.ts (1)
8-25: LGTM - Function signature and null checks.The function correctly handles null state and provides detailed logging. Type annotations are appropriate.
doc-agents/src/agent/agent_pulse/streaming-processor.ts (2)
28-39: Runtime type workaround noted.The comment on line 30-31 indicates a runtime mismatch with AI SDK types (
textDeltavstext). This defensive fallback is reasonable, but consider filing an issue with the AI SDK if the types are incorrect.
94-106: LGTM - Error handling in stream processor.Proper error chunk emission and stream closure on failure.
doc-agents/src/agent/agent_pulse/context-builder.ts (2)
7-32: LGTM - Context building with graceful fallback.Good error handling that returns fallback context on API failure rather than throwing.
37-50: LGTM - Tutorial info helper.Handles edge cases well: missing tutorialId, unknown tutorial, completed tutorial, and in-progress tutorial.
lib/api/services/agentPulse.ts (1)
48-72: LGTM - Streaming setup with timeout.Good use of
AbortControllerwith timeout, proper headers including optional Bearer token, and cleanup in finally block.doc-agents/src/agent/agent_pulse/tutorial.ts (2)
115-122: LGTM!The
TutorialSnippetinterface is well-defined with appropriate optional fields.
137-190: LGTM!The function follows the same consistent pattern as the other API functions with proper error handling and logging.
doc-agents/src/agent/agent_pulse/types.ts (4)
3-20: LGTM!The
ConversationMessage,TutorialState, andTutorialinterfaces are well-defined with appropriate types.
22-28: LGTM!The generic
ApiResponse<T>interface provides a consistent structure for API responses with proper error handling fields.
30-39: LGTM!The
ActionTypeenum andActioninterface are appropriately structured. The single enum value is acceptable as a foundation for future action types.
54-62: ConsolidateStreamingChunkinterface to a single location.
StreamingChunkis defined in bothdoc-agents/src/agent/agent_pulse/types.tsandlib/api/services/agentPulse.ts. The definitions differ on thetutorialDatafield—the first usesTutorialData(strongly typed) while the second usesany(untyped). This duplication creates a maintenance burden and risks type drift. Move the definition to a shared location and export it from there.
| onTutorialData: async (data) => { | ||
| finalTutorialData = data; | ||
|
|
||
| // Update user's tutorial progress | ||
| await TutorialStateManager.updateTutorialProgress( | ||
| userId, | ||
| data.tutorialId, | ||
| data.currentStep, | ||
| data.totalSteps | ||
| ); | ||
|
|
||
| controller.enqueue( | ||
| encoder.encode( | ||
| `data: ${JSON.stringify({ type: 'tutorial-data', tutorialData: data })}\n\n` | ||
| ) | ||
| ); | ||
| }, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Async callback error may be silently lost.
The onTutorialData callback is async but callAgentPulseStreaming invokes it via callbacks.onTutorialData?.(data) without await. If TutorialStateManager.updateTutorialProgress throws, the error becomes an unhandled promise rejection.
Consider wrapping the async operation in a try-catch:
🛡️ Suggested fix
onTutorialData: async (data) => {
finalTutorialData = data;
// Update user's tutorial progress
- await TutorialStateManager.updateTutorialProgress(
- userId,
- data.tutorialId,
- data.currentStep,
- data.totalSteps
- );
+ try {
+ await TutorialStateManager.updateTutorialProgress(
+ userId,
+ data.tutorialId,
+ data.currentStep,
+ data.totalSteps
+ );
+ } catch (err) {
+ console.error('[tutorial-progress] update failed:', err instanceof Error ? err.message : String(err));
+ }
controller.enqueue(📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| onTutorialData: async (data) => { | |
| finalTutorialData = data; | |
| // Update user's tutorial progress | |
| await TutorialStateManager.updateTutorialProgress( | |
| userId, | |
| data.tutorialId, | |
| data.currentStep, | |
| data.totalSteps | |
| ); | |
| controller.enqueue( | |
| encoder.encode( | |
| `data: ${JSON.stringify({ type: 'tutorial-data', tutorialData: data })}\n\n` | |
| ) | |
| ); | |
| }, | |
| onTutorialData: async (data) => { | |
| finalTutorialData = data; | |
| // Update user's tutorial progress | |
| try { | |
| await TutorialStateManager.updateTutorialProgress( | |
| userId, | |
| data.tutorialId, | |
| data.currentStep, | |
| data.totalSteps | |
| ); | |
| } catch (err) { | |
| console.error('[tutorial-progress] update failed:', err instanceof Error ? err.message : String(err)); | |
| } | |
| controller.enqueue( | |
| encoder.encode( | |
| `data: ${JSON.stringify({ type: 'tutorial-data', tutorialData: data })}\n\n` | |
| ) | |
| ); | |
| }, |
🤖 Prompt for AI Agents
In @app/api/sessions/[sessionId]/messages/route.ts around lines 169 - 185, The
async onTutorialData handler can throw and is invoked without awaiting in
callAgentPulseStreaming, risking unhandled rejections; modify the invocation to
await callbacks.onTutorialData?.(data) or wrap the handler body in a try-catch
so TutorialStateManager.updateTutorialProgress errors are caught and logged
before calling controller.enqueue/encoder.encode, ensuring any thrown error is
handled and does not become an unhandled promise rejection.
| onFinish: async () => { | ||
| // Save the assistant message | ||
| const assistantMessage: Message = { | ||
| id: assistantMessageId, | ||
| author: "ASSISTANT", | ||
| content: accumulatedContent, | ||
| timestamp: getCurrentTimestamp(), | ||
| tutorialData: finalTutorialData, | ||
| }; | ||
|
|
||
| const finalSession = { | ||
| ...updatedSession, | ||
| messages: [...updatedSession.messages, assistantMessage], | ||
| }; | ||
|
|
||
| await setKVValue(sessionKey, finalSession, { | ||
| storeName: config.kvStoreName, | ||
| }); | ||
|
|
||
| // Trigger background title generation if missing | ||
| // Do not await to avoid delaying the client stream completion | ||
| void generateAndPersistTitle(sessionKey, finalSession); | ||
|
|
||
| // Send the final session in the finish event | ||
| controller.enqueue( | ||
| encoder.encode( | ||
| `data: ${JSON.stringify({ | ||
| type: "finish", | ||
| session: finalSession, | ||
| })}\n\n` | ||
| ) | ||
| ); | ||
|
|
||
| controller.close(); | ||
| }, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Async onFinish callback - same unhandled rejection risk.
Similar to onTutorialData, this async callback may have unhandled promise rejections since the caller doesn't await it. If setKVValue fails, the error won't propagate to the outer try-catch.
🛡️ Suggested fix - wrap in try-catch
onFinish: async () => {
+ try {
// Save the assistant message
const assistantMessage: Message = {
id: assistantMessageId,
author: "ASSISTANT",
content: accumulatedContent,
timestamp: getCurrentTimestamp(),
tutorialData: finalTutorialData,
};
const finalSession = {
...updatedSession,
messages: [...updatedSession.messages, assistantMessage],
};
await setKVValue(sessionKey, finalSession, {
storeName: config.kvStoreName,
});
// Trigger background title generation if missing
void generateAndPersistTitle(sessionKey, finalSession);
// Send the final session in the finish event
controller.enqueue(
encoder.encode(
`data: ${JSON.stringify({
type: "finish",
session: finalSession,
})}\n\n`
)
);
controller.close();
+ } catch (err) {
+ console.error('[onFinish] error:', err instanceof Error ? err.message : String(err));
+ controller.enqueue(
+ encoder.encode(
+ `data: ${JSON.stringify({ type: 'error', error: 'Failed to save session' })}\n\n`
+ )
+ );
+ controller.close();
+ }
},| === TOOL-USAGE RULES (must follow) === | ||
| - startTutorialById must only be used when user select a tutorial. If the user starts a new tutorial, the step number should be set to one. Valid step is between 1 and totalSteps of the specific tutorial. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Tool name mismatch in system prompt.
The prompt references startTutorialById but the actual tool is named startTutorialAtStep (as seen in lines 80-81 and in tools.ts). This inconsistency may confuse the LLM.
🐛 Fix tool name reference
=== TOOL-USAGE RULES (must follow) ===
-- startTutorialById must only be used when user select a tutorial. If the user starts a new tutorial, the step number should be set to one. Valid step is between 1 and totalSteps of the specific tutorial.
+- startTutorialAtStep must only be used when user select a tutorial. If the user starts a new tutorial, the step number should be set to one. Valid step is between 1 and totalSteps of the specific tutorial.📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| === TOOL-USAGE RULES (must follow) === | |
| - startTutorialById must only be used when user select a tutorial. If the user starts a new tutorial, the step number should be set to one. Valid step is between 1 and totalSteps of the specific tutorial. | |
| === TOOL-USAGE RULES (must follow) === | |
| - startTutorialAtStep must only be used when user select a tutorial. If the user starts a new tutorial, the step number should be set to one. Valid step is between 1 and totalSteps of the specific tutorial. |
🤖 Prompt for AI Agents
In @doc-agents/src/agent/agent_pulse/context-builder.ts around lines 85 - 86,
The system prompt rule incorrectly references startTutorialById; update the
prompt text to reference the actual tool name startTutorialAtStep (used in
tools.ts and around lines 80-81) and adjust the rule wording so it instructs
using startTutorialAtStep only when the user selects a tutorial, defaulting the
step to 1 for new tutorials and validating that the step is between 1 and the
tutorial's totalSteps.
| export function createStreamingProcessor( | ||
| result: StreamTextResult<>, | ||
| state: { action: Action | null }, | ||
| logger: any | ||
| ): ReadableStream { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Fix missing type parameter for StreamTextResult.
The static analysis correctly flags StreamTextResult<> as having an empty type parameter. This is a parse error that may cause TypeScript compilation to fail.
🐛 Suggested fix
export function createStreamingProcessor(
- result: StreamTextResult<>,
+ result: StreamTextResult<Record<string, Tool>>,
state: { action: Action | null },
logger: any
): ReadableStream {Alternatively, if tools type isn't important:
- result: StreamTextResult<>,
+ result: StreamTextResult<any>,📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| export function createStreamingProcessor( | |
| result: StreamTextResult<>, | |
| state: { action: Action | null }, | |
| logger: any | |
| ): ReadableStream { | |
| export function createStreamingProcessor( | |
| result: StreamTextResult<any>, | |
| state: { action: Action | null }, | |
| logger: any | |
| ): ReadableStream { |
🧰 Tools
🪛 Biome (2.1.2)
[error] 10-10: Expected a type parameter but instead found '>'.
Expected a type parameter here.
(parse)
🤖 Prompt for AI Agents
In @doc-agents/src/agent/agent_pulse/streaming-processor.ts around lines 9 - 13,
The function signature uses StreamTextResult<> with an empty type parameter
which is a parse/TS error; update the signature in createStreamingProcessor to
supply an appropriate generic (e.g., StreamTextResult<string> or
StreamTextResult<any> / StreamTextResult<unknown> depending on expected payload)
and adjust any callers or imports accordingly so the generic is consistent
across usages (ensure the import/definition of StreamTextResult supports the
chosen type).
| // Process tutorial state and fetch complete tutorial data if available | ||
| const finalTutorialData = await handleTutorialState(state, logger); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Parameter mismatch for handleTutorialState.
handleTutorialState expects a ctx object with a logger property (uses ctx.logger.info, etc.), but this call passes logger directly as the second argument. This will cause runtime errors.
🐛 Suggested fix
// Process tutorial state and fetch complete tutorial data if available
- const finalTutorialData = await handleTutorialState(state, logger);
+ const finalTutorialData = await handleTutorialState(state, { logger });📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| // Process tutorial state and fetch complete tutorial data if available | |
| const finalTutorialData = await handleTutorialState(state, logger); | |
| // Process tutorial state and fetch complete tutorial data if available | |
| const finalTutorialData = await handleTutorialState(state, { logger }); |
🤖 Prompt for AI Agents
In @doc-agents/src/agent/agent_pulse/streaming-processor.ts around lines 74 -
75, The call site for handleTutorialState in streaming-processor.ts passes
logger directly but handleTutorialState expects a ctx object with a logger
property (it calls ctx.logger.info, etc.); fix by passing an object containing
the logger (e.g., { logger }) or the existing ctx object instead of the bare
logger so the parameter shape matches handleTutorialState, and update any other
nearby calls to handleTutorialState to use the same ctx-shaped argument.
| interface TutorialStepResponseData { | ||
| tutorialId: string; | ||
| totalSteps: number; | ||
| currentStep: number; | ||
| tutorialStep: { | ||
| title: string; | ||
| mdx: string; | ||
| snippets: TutorialSnippet[]; | ||
| totalSteps: number; | ||
| estimatedTime?: string; | ||
| }; | ||
| } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Export TutorialStepResponseData for consumers.
This interface is used in the public return type of getTutorialStep (line 141) but is not exported. Consumers won't be able to properly type variables receiving this data.
-interface TutorialStepResponseData {
+export interface TutorialStepResponseData {🤖 Prompt for AI Agents
In @doc-agents/src/agent/agent_pulse/tutorial.ts around lines 124 - 135, The
interface TutorialStepResponseData is declared but not exported, yet it's used
as the public return type of getTutorialStep; make it available to consumers by
adding an export to the declaration (export interface TutorialStepResponseData)
so external callers can import the type, and ensure any related exports/barrel
files that should re-export it include this symbol if necessary; update
references to import the exported TutorialStepResponseData where used.
| // Process any remaining data | ||
| if (buffer.length > 0 && buffer.startsWith('data: ')) { | ||
| try { | ||
| const chunk = JSON.parse(buffer.slice(6)) as StreamingChunk; | ||
| if (chunk.type === 'text-delta' && chunk.textDelta) { | ||
| callbacks.onTextDelta?.(chunk.textDelta); | ||
| } else if (chunk.type === 'finish') { | ||
| callbacks.onFinish?.(); | ||
| } | ||
| } catch (error) { | ||
| console.error('Error parsing final SSE chunk:', error); | ||
| } | ||
| } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Incomplete SSE handling for remaining buffer.
The final buffer processing only handles text-delta and finish chunk types, but other types like status, tutorial-data, and error could also be in the final buffer. Consider handling all chunk types consistently.
🛡️ Suggested fix
// Process any remaining data
if (buffer.length > 0 && buffer.startsWith('data: ')) {
try {
const chunk = JSON.parse(buffer.slice(6)) as StreamingChunk;
if (chunk.type === 'text-delta' && chunk.textDelta) {
callbacks.onTextDelta?.(chunk.textDelta);
+ } else if (chunk.type === 'status') {
+ callbacks.onStatus?.(chunk.message || '', chunk.category);
+ } else if (chunk.type === 'tutorial-data' && chunk.tutorialData) {
+ callbacks.onTutorialData?.(chunk.tutorialData);
} else if (chunk.type === 'finish') {
callbacks.onFinish?.();
+ } else if (chunk.type === 'error') {
+ callbacks.onError?.(chunk.error || 'Unknown error');
}
} catch (error) {
console.error('Error parsing final SSE chunk:', error);
}
}🤖 Prompt for AI Agents
In @lib/api/services/agentPulse.ts around lines 124 - 136, The final SSE buffer
parsing only handles text-delta and finish types; update the try block that
parses StreamingChunk from buffer (the buffer variable and
JSON.parse(buffer.slice(6))) to also handle other chunk types consistently by
invoking the corresponding callbacks on the callbacks object: call
callbacks.onStatus for type === 'status', callbacks.onTutorialData for type ===
'tutorial-data' and callbacks.onError for type === 'error' (preserving the
existing callbacks.onTextDelta and callbacks.onFinish handling), and add a
default branch to log or ignore unknown chunk.type values; keep the surrounding
try/catch intact to report parse errors.
Summary by CodeRabbit
New Features
Documentation
Infrastructure Updates
✏️ Tip: You can customize this high-level summary in your review settings.