Engineering implementation report documenting the structure, contracts, validation models, and error behaviors for the new @corsair-dev/streamtime plugin package.
This report documents the architectural design and code structure of the Streamtime plugin integration. Streamtime is a productivity and project-management platform used by creative businesses such as agencies, design studios, and other creative teams.
The integration introduces Streamtime capabilities to the Corsair framework, allowing Corsair and AI agents to programmatically query organisation details, roles, and user segments. This exposes Streamtime's API functionality directly to agents, avoiding manual operation overlays. The integration naturally covers three primary categories:
The implementation adheres to Corsair’s standard plugin/provider architectural conventions rather than establishing a custom layout. The project was executed with the following engineering objectives:
The package registers and implements four Streamtime API operations under the streamtime tool schema:
| Operation | HTTP Method / API Action | Purpose |
|---|---|---|
STREAMTIME_ORGANISATION_GET_ORGANISATION |
GET /v2/organisation |
Retrieves the authenticated organisation's details (such as name, domain, address, country, and currency). |
STREAMTIME_ROLES_GET_ROLE |
GET /v2/roles/:role_id |
Retrieves detailed properties (ID, name, and archive status) of a specific workspace role. |
STREAMTIME_LIST_ROLES |
GET /v2/roles |
Lists all active and archived roles defined in the organisation. |
STREAMTIME_USERS_LIST_SAVED_SEGMENTS |
GET /v2/users/:user_id/saved_segments |
Retrieves all saved search/filter segments associated with a specific user profile. |
To establish type-safety boundaries and prevent malformed data from polluting the framework context, the Streamtime integration utilizes zod schemas to validate all inputs and responses before they pass the package boundaries.
For example, workspace roles are validated and verified against the following Zod contracts:
// packages/streamtime/endpoints/types.ts
export const RoleSchema = z.object({
id: z.number().int().describe('The ID of the role'),
name: z.string().describe('The name of the role'),
active: z.boolean().describe('Whether the role is active or archived'),
});
export const GetRoleInputSchema = z.object({
role_id: z.number().int().describe('Role ID'),
});
export type GetRoleInput = z.infer<typeof GetRoleInputSchema>;
export type GetRoleResponse = z.infer<typeof RoleSchema>;
The client propagates exceptions using a custom error class (StreamtimeAPIError), wrapping underlying system errors while preserving descriptive message logs. This avoids silent failures and guarantees that Corsair's handler layer receives clean exception indicators.
The client request method handles exceptions as follows:
// packages/streamtime/client.ts
try {
return await request<T>(config, requestOptions);
} catch (error) {
if (error instanceof Error) {
throw new StreamtimeAPIError(error.message);
}
throw new StreamtimeAPIError('Unknown error');
}
Corsair intercepts exceptions using custom error handlers. Specifically, rate-limit warnings (HTTP 429 — Too Many Requests) are matched via status values or message keywords, returning the server's retry recommendations to orchestrate a recovery flow:
// packages/streamtime/error-handlers.ts
export const errorHandlers = {
RATE_LIMIT_ERROR: {
match: (error: Error) => {
if (error instanceof ApiError && error.status === 429) return true;
const msg = error.message.toLowerCase();
return msg.includes('rate_limited') || msg.includes('429');
},
handler: async (error: Error) => {
let retryAfterMs: number | undefined;
if (error instanceof ApiError && error.retryAfter !== undefined) {
retryAfterMs = error.retryAfter;
}
return { maxRetries: 5, headersRetryAfterMs: retryAfterMs };
},
},
AUTH_ERROR: {
match: (error: Error) => {
if (error instanceof ApiError && error.status === 401) return true;
const msg = error.message.toLowerCase();
return msg.includes('unauthorized') || msg.includes('invalid_auth');
},
handler: async () => ({ maxRetries: 0 }),
},
DEFAULT: {
match: () => true,
handler: async () => ({ maxRetries: 0 }),
},
} satisfies CorsairErrorHandler;
The package has been verified locally through build checks, TypeScript compilation verification, and automated tests. The verification suite is divided into two primary test files, covering a total of 10 unit tests:
schema.test.ts (2 unit tests): Asserts schema compliance, structure initialization, and semantic versioning formatting.endpoints.test.ts (8 unit tests): Verifies endpoint execution, parameter input validation, authentication client configuration (such as key builders), and error boundaries (like AuthMissingError handling).Local verification steps executed during development include:
PR reviewed by maintainer Ambikesh, with feedback incorporated before merge.
The integration was developed and merged following Corsair’s contribution workflow guidelines:
rujitha-g/corsair, and a dedicated feature branch was created for the Streamtime integration.@corsair-dev/streamtime plugin structure, registered the package in the core provider mapping constants (packages/corsair/core/constants.ts), and wrote comprehensive unit tests.AI-assisted development tooling was used during implementation and review to accelerate integration cycles and ensure compatibility. AI assistance was utilized to:
All AI-generated suggestions were verified through local execution, compiler checks, CI validations, and final maintainer reviews.
The Streamtime integration successfully extends Corsair with robust productivity and project management features, allowing AI agents to query organisation states, active roles, and saved segments. Built entirely on Corsair's plugin-provider guidelines, the module integrates custom client requests with strict Zod validation schemas, robust error propagation, and HTTP 429 rate-limiting retries. The contribution has successfully completed code reviews, passed CI pipelines, and been merged by the maintainers into the main codebase.