chore: import upstream snapshot with attribution

This commit is contained in:
wehub-resource-sync
2026-07-13 13:34:48 +08:00
commit 77bb5bf71f
3762 changed files with 353249 additions and 0 deletions
+147
View File
@@ -0,0 +1,147 @@
import sdk, { z } from '@botpress/sdk'
import { Task, Project, Section, SharedLabel } from './entities'
export const actions = {
changeTaskPriority: {
title: 'Change Task Priority',
description: 'Change the priority of a task',
input: {
schema: z.object({
taskId: Task.schema.shape.id,
priority: Task.schema.shape.priority,
}),
},
output: {
schema: z.object({}),
},
},
getTaskId: {
title: 'Get Task ID',
description: 'Get the ID of the first task matching the given name',
input: {
schema: z.object({
name: z.string().title('Name').describe('The name of the task to search for'),
// NOTE: this actually refers to the `content` property of the Task
// entity: the `name` property does not exist
}),
},
output: {
schema: z.object({
taskId: Task.schema.shape.id.nullable(),
}),
},
},
getProjectId: {
title: 'Get Project ID',
description: 'Get the ID of the project',
input: {
schema: z.object({
name: Project.schema.shape.name,
}),
},
output: {
schema: z.object({
projectId: Project.schema.shape.id.nullable(),
}),
},
},
getAllProjects: {
title: 'Get All Projects',
description: 'Get all projects',
input: {
schema: z.object({}),
},
output: {
schema: z.object({
projects: z.array(Project.schema).title('Projects').describe('All projects that are available to the user'),
}),
},
},
getAllSections: {
title: 'Get All Sections',
description: 'Get all sections in a project',
input: {
schema: z.object({
projectId: Project.schema.shape.id
.optional()
.title('Project ID (optional)')
.describe('The ID of the project. If omitted, the sections of all projects will be returned.'),
}),
},
output: {
schema: z.object({
sections: z
.array(Section.schema)
.title('Sections')
.describe('All sections in the project, or all sections in all projects if projectId is omitted'),
}),
},
},
getAllTasks: {
title: 'Get All Tasks',
description: 'Find tasks using optional filters',
input: {
schema: z.object({
projectId: Project.schema.shape.id
.optional()
.title('Filter by Project ID (optional)')
.describe('The ID of the project. If omitted, tasks from all projects will be included in the results.'),
sectionId: Section.schema.shape.id
.optional()
.title('Filter by Section ID (optional)')
.describe('The ID of the section. If omitted, tasks from all sections will be included in the results.'),
labelName: SharedLabel.schema.shape.name
.optional()
.title('Filter by Label Name (optional)')
.describe('The name of the label. If omitted, tasks with any label will be included in the results.'),
}),
},
output: {
schema: z.object({
tasks: z.array(Task.schema).title('Tasks').describe('All matching tasks'),
}),
},
},
createNewTask: {
title: 'Create New Task',
description: 'Create a new task',
input: {
schema: z.object({
content: Task.schema.shape.content,
description: Task.schema.shape.description.optional(),
projectId: Project.schema.shape.id
.optional()
.title('Project ID (optional)')
.describe("The ID of the project. If omitted, the task will be added to the user's Inbox."),
sectionId: Section.schema.shape.id
.optional()
.title('Section ID (optional)')
.describe('The ID of section to put task into.'),
labelNames: z
.array(SharedLabel.schema.shape.name)
.optional()
.title('Label Names (optional)')
.describe('The names of the labels to add to the task. If omitted, no label will be added.'),
parentTaskId: Task.schema.shape.id
.optional()
.title('Parent Task ID (optional)')
.describe('The ID of the parent task. If omitted, the task will have no parent task.'),
priority: Task.schema.shape.priority
.optional()
.title('Priority (optional)')
.describe('The priority level of the task, from 1 (normal) to 4 (urgent).'),
dueDate: Task.schema.shape.dueDate
.optional()
.title('Due Date')
.describe(
'The due date of the task. Must be in RFC3339 format in UTC. If omitted, the task will have no due date.'
),
}),
},
output: {
schema: z.object({
taskId: Task.schema.shape.id,
}),
},
},
} as const satisfies sdk.IntegrationDefinitionProps['actions']
@@ -0,0 +1,27 @@
import * as sdk from '@botpress/sdk'
export const channels = {
comments: {
title: 'Task comments',
description: 'Comment thread on a task',
messages: {
text: sdk.messages.defaults.text,
},
conversation: {
tags: {
id: {
title: 'Task ID',
description: 'The ID of the task',
},
},
},
message: {
tags: {
id: {
title: 'Comment ID',
description: 'The ID of the comment',
},
},
},
},
} as const satisfies sdk.IntegrationDefinitionProps['channels']
@@ -0,0 +1,23 @@
import sdk, { z } from '@botpress/sdk'
export const configuration = {
schema: z.object({}),
identifier: {
linkTemplateScript: 'linkTemplate.vrl',
required: true,
},
} as const satisfies sdk.IntegrationDefinitionProps['configuration']
export const configurations = {
apiToken: {
title: 'Manual configuration',
description: 'Configure manually by supplying an API token',
schema: z.object({
apiToken: z.string().title('API Token').describe('The API token to authenticate with the Todoist API'),
}),
},
} satisfies sdk.IntegrationDefinitionProps['configurations']
export const identifier = {
extractScript: 'extract.vrl',
} as const satisfies sdk.IntegrationDefinitionProps['identifier']
@@ -0,0 +1,26 @@
// documentation for Color: https://developer.todoist.com/guides/#colors
export namespace Color {
export const names = [
'berry_red',
'red',
'orange',
'yellow',
'olive_green',
'lime_green',
'green',
'mint_green',
'teal',
'sky_blue',
'light_blue',
'blue',
'grape',
'violet',
'lavender',
'magenta',
'salmon',
'charcoal',
'gunmetal',
'taupe',
] as const
}
@@ -0,0 +1,27 @@
import { z } from '@botpress/sdk'
// documentation for Comment: https://developer.todoist.com/rest/v2/#comments
export namespace Comment {
const _fields = {
id: z.string().title('ID').describe('The ID of the comment'),
taskId: z
.string()
.title('Task ID')
.optional()
.describe('The ID of the task this comment belongs to. Omitted if the comment belongs to a project.'),
projectId: z
.string()
.title('Project ID')
.optional()
.describe('The ID of the project this comment belongs to. Omitted if the comment belongs to a task.'),
postedAt: z.string().title('Posted At').describe('Date and time when comment was added, RFC3339 format in UTC.'),
content: z
.string()
.title('Content')
.describe('The text of the comment. This value may contain markdown-formatted text and hyperlinks.'),
} as const
export const schema = z.object(_fields)
export type InferredType = z.infer<typeof schema>
}
@@ -0,0 +1,44 @@
import sdk from '@botpress/sdk'
import { Color } from './color'
import { Comment } from './comment'
import { PersonalLabel } from './personal-label'
import { Project } from './project'
import { Section } from './section'
import { SharedLabel } from './shared-label'
import { Task } from './task'
export { Comment, PersonalLabel, Project, Section, SharedLabel, Task, Color }
export const entities = {
task: {
title: 'Task',
description: 'A task in Todoist',
schema: Task.schema,
},
project: {
title: 'Project',
description: 'A project in Todoist',
schema: Project.schema,
},
section: {
title: 'Section',
description: 'A section in a Todoist project',
schema: Section.schema,
},
comment: {
title: 'Comment',
description: 'A comment on a Todoist task',
schema: Comment.schema,
},
personalLabel: {
title: 'Personal Label',
description: 'A personal label in Todoist',
schema: PersonalLabel.schema,
},
sharedLabel: {
title: 'Shared Label',
description: 'A shared label in Todoist',
schema: SharedLabel.schema,
},
} as const satisfies sdk.IntegrationDefinitionProps['entities']
@@ -0,0 +1,21 @@
import { z } from '@botpress/sdk'
import { Color } from './color'
// documentation for Label: https://developer.todoist.com/rest/v2/#labels
export namespace PersonalLabel {
const _fields = {
id: z.string().title('ID').describe('The ID of the label.'),
name: z.string().title('Name').describe('The name of the label.'),
color: z.enum(Color.names).title('Color Name').describe('The color of the label.'),
orderWithinList: z
.number()
.title('Order Within List')
.nonnegative()
.describe("Numerical index indicating label's order within the user's label list."),
isFavorite: z.boolean().title('Is Favorite?').describe('Whether the label is marked as favorite or not.'),
} as const
export const schema = z.object(_fields)
export type InferredType = z.infer<typeof schema>
}
@@ -0,0 +1,36 @@
import { z } from '@botpress/sdk'
import { Color } from './color'
// documentation for Project: https://developer.todoist.com/rest/v2/#projects
export namespace Project {
const _fields = {
id: z.string().title('ID').describe('The ID of the project.'),
name: z.string().title('Name').describe('The name of the project.'),
color: z.enum(Color.names).title('Color Name').describe('The color of the project.'),
parentProjectId: z
.string()
.title('Parent Project ID')
.optional()
.describe('The ID of the parent project. Omitted if the project has no parent project.'),
positionWithinParent: z
.number()
.title('Position Within Parent')
.describe(
"Numerical index indicating project's order within its parent project (read-only). Will be 0 for inbox projects."
),
numberOfComments: z
.number()
.title('Number of Comments')
.nonnegative()
.describe('The number of comments on the project.'),
isShared: z.boolean().title('Is Shared?').describe('Whether the project is shared or not.'),
isFavorite: z.boolean().title('Is Favorite?').describe('Whether the project is marked as favorite or not.'),
isInboxProject: z.boolean().title('Is Inbox Project?').describe("Whether the project is the user's inbox."),
isTeamInbox: z.boolean().title('Is Team Inbox?').describe('Whether the project is a team inbox.'),
webUrl: z.string().title('Web URL').describe('The URL of the project in the Todoist web app.'),
} as const
export const schema = z.object(_fields)
export type InferredType = z.infer<typeof schema>
}
@@ -0,0 +1,18 @@
import { z } from '@botpress/sdk'
// documentation for Section: https://developer.todoist.com/rest/v2/#sections
export namespace Section {
const _fields = {
id: z.string().title('ID').describe('The ID of the section.'),
name: z.string().title('Name').describe('The name of the section.'),
projectId: z.string().title('Project ID').optional().describe('The ID of the project this section belongs to.'),
positionWithinParent: z
.number()
.title('Position Within Parent')
.describe("Numerical index indicating section's order within its parent project."),
} as const
export const schema = z.object(_fields)
export type InferredType = z.infer<typeof schema>
}
@@ -0,0 +1,25 @@
import { z } from '@botpress/sdk'
// documentation for Label: https://developer.todoist.com/rest/v2/#labels
/**
* Shared labels are ephemeral in nature. They only exist as long as at least
* one task is associated with them. Once all tasks are removed from a shared
* label, the label ceases to exist.
*
* A user can convert a shared label to a personal label at any time. The label
* will then become customizable and will remain in the account even if not
* assigned to any active tasks.
*
* Likewise, a personal label can be converted to a shared label by the user if
* they no longer require them to be stored against their account, but they
* still appear on shared tasks.
*/
export namespace SharedLabel {
const _fields = {
name: z.string().title('Name').describe('The name of the label.'),
} as const
export const schema = z.object(_fields)
export type InferredType = z.infer<typeof schema>
}
@@ -0,0 +1,98 @@
import { z } from '@botpress/sdk'
/**
* Note: `item` is an old term used by Todoist to refer to tasks in their old
* Sync API. While the REST API uses the term `task` and sends us Task entities,
* we still receive Item entities in webhook events. Todoist is currently in the
* process of phasing out the Item entity in favor of the Task entity, but for
* now we must manually do some mapping between the two, since we only want to
* expose the Task entity to the user.
*/
// documentation for Task: https://developer.todoist.com/rest/v2/#tasks
// documentation for Item: https://developer.todoist.com/sync/v9/#items
export namespace Task {
const _fields = {
id: z.string().title('ID').describe('The ID of the task'),
projectId: z.string().title('Project ID').describe('The ID of the project this task belongs to (read-only).'),
sectionId: z
.string()
.title('Section ID')
.optional()
.describe('The ID of the section this task belongs to (read-only). Omitted if the task is not in a section.'),
content: z
.string()
.title('Content')
.describe('The text of the task. This value may contain markdown-formatted text and hyperlinks.'),
description: z
.string()
.title('Description')
.describe('A description for the task. This value may contain markdown-formatted text and hyperlinks.'),
isCompleted: z.boolean().title('Is Completed?').describe('Whether the task is completed or not.'),
labels: z
.array(z.string().title('Label Name').describe('The name of a label associated with the task.'))
.title('Labels')
.describe(
'The labels associated with the task. This is a list of names that may represent either personal or shared labels.'
),
parentTaskId: z
.string()
.title('Parent Task ID')
.optional()
.describe('The ID of the parent task (read-only). Omitted if the task has no parent task.'),
positionWithinParent: z
.number()
.title('Position Within Parent')
.describe(
"Numerical index indicating task's order within its parent (task, or project for top-level tasks) (read-only)."
),
priority: z
.number()
.title('Priority')
.min(1)
.max(4)
.describe('Task priority from 1 (urgent) to 4 (lowest, default value).'),
dueDate: z
.string()
.title('Due Date')
.optional()
.describe('The due date of the task. Omitted if the task has no due date.'),
isRecurringDueDate: z
.boolean()
.title('Is Recurring Due Date?')
.describe('Whether the due date is recurring or not.'),
webUrl: z
.string()
.title('Web URL')
.describe('URL to access this task in the Todoist web or mobile applications (read-only).'),
numberOfComments: z
.number()
.title('Number of Comments')
.nonnegative()
.describe('The number of comments associated with the task (read-only).'),
createdAt: z.string().title('Created At').describe('The date when the task was created (read-only).'),
createdBy: z.string().title('Created By ID').describe('The ID of the user who created the task (read-only).'),
assignee: z
.string()
.title('Assignee ID')
.optional()
.describe('The ID of the user to whom the task is assigned. Omitted if the task is not assigned.'),
assigner: z
.string()
.title('Assigner ID')
.optional()
.describe('The ID of the user who assigned the task (read-only). Omitted if the task is not assigned.'),
duration: z
.object({
amount: z.number().title('Amount').positive().describe('The amount of time.'),
unit: z.enum(['minute', 'day']).title('Unit').describe('The unit of time.'),
})
.title('Duration')
.optional()
.describe('The duration of the task. Omitted if the task has no duration.'),
} as const
export const schema = z.object(_fields)
export type InferredType = z.infer<typeof schema>
}
@@ -0,0 +1,36 @@
import sdk, { z } from '@botpress/sdk'
import { Task } from './entities'
export const events = {
taskAdded: {
title: 'Task Added',
description: 'A task has been added',
schema: z.object({
id: Task.schema.shape.id,
content: Task.schema.shape.content,
description: Task.schema.shape.description,
priority: Task.schema.shape.priority,
}),
},
taskPriorityChanged: {
title: 'Task Priority Changed',
description:
'The priority of a task has been changed. The old priority is only available if the bot user is at the origin of the change',
schema: z.object({
id: Task.schema.shape.id,
newPriority: Task.schema.shape.priority.title('New Priority'),
oldPriority: Task.schema.shape.priority.optional().title('Old Priority'),
}),
},
taskCompleted: {
title: 'Task Completed',
description: 'A task has been completed',
schema: z.object({
user_id: z.string().title('User ID').describe('The ID of the user who completed the task'),
id: Task.schema.shape.id,
content: Task.schema.shape.content,
description: Task.schema.shape.description,
priority: Task.schema.shape.priority,
}),
},
} as const satisfies sdk.IntegrationDefinitionProps['events']
@@ -0,0 +1,8 @@
export * from './actions'
export * from './channels'
export * from './configuration'
export * from './entities'
export * from './events'
export * from './secrets'
export * from './states'
export * from './user-tags'
@@ -0,0 +1,16 @@
import sdk from '@botpress/sdk'
export const secrets = {
CLIENT_ID: {
optional: false,
description: 'Client ID in the App Management page of your Todoist app',
},
CLIENT_SECRET: {
optional: false,
description: 'Client Secret in the App Management page of your Todoist app',
},
WEBHOOK_SHARED_SECRET: {
optional: false,
description: 'Webhook shared secret',
},
} as const satisfies sdk.IntegrationDefinitionProps['secrets']
@@ -0,0 +1,21 @@
import sdk, { z } from '@botpress/sdk'
export const states = {
credentials: {
type: 'integration',
schema: z.object({
accessToken: z
.string()
.title('Access Token')
.describe('The access token used to communicate with the Todoist API'),
}),
},
// TODO: This state is unused. Delete it in the next major version.
configuration: {
type: 'integration',
schema: z.object({
botUserId: z.string().optional().title('Bot User ID').describe('The ID of the bot user in Todoist'),
}),
},
} as const satisfies sdk.IntegrationDefinitionProps['states']
@@ -0,0 +1,10 @@
import sdk from '@botpress/sdk'
export const user = {
tags: {
id: {
title: 'Todoist User ID',
description: 'The unique ID of the user on Todoist',
},
},
} as const satisfies sdk.IntegrationDefinitionProps['user']