terse-cli 0.1.0__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (50) hide show
  1. terse_cli-0.1.0/.gitignore +30 -0
  2. terse_cli-0.1.0/PKG-INFO +129 -0
  3. terse_cli-0.1.0/README.md +102 -0
  4. terse_cli-0.1.0/pyproject.toml +45 -0
  5. terse_cli-0.1.0/shared/ApiRoutes.ts +350 -0
  6. terse_cli-0.1.0/shared/ApprovalTypes.ts +36 -0
  7. terse_cli-0.1.0/shared/ClientBoundTools.ts +78 -0
  8. terse_cli-0.1.0/shared/Configs.ts +874 -0
  9. terse_cli-0.1.0/shared/DonatedState.ts +14 -0
  10. terse_cli-0.1.0/shared/Entities.ts +7 -0
  11. terse_cli-0.1.0/shared/FrontendRoutes.ts +56 -0
  12. terse_cli-0.1.0/shared/Integrations.ts +291 -0
  13. terse_cli-0.1.0/shared/InvalidationKeys.ts +218 -0
  14. terse_cli-0.1.0/shared/ModelEvents.ts +89 -0
  15. terse_cli-0.1.0/shared/Notifications.ts +49 -0
  16. terse_cli-0.1.0/shared/RunHistoryTypes.ts +123 -0
  17. terse_cli-0.1.0/shared/SentNotifications.ts +32 -0
  18. terse_cli-0.1.0/shared/SocketEvents.ts +57 -0
  19. terse_cli-0.1.0/shared/Survey.ts +10 -0
  20. terse_cli-0.1.0/shared/TicketSystem.ts +170 -0
  21. terse_cli-0.1.0/shared/ToolDisplayUtils.ts +1089 -0
  22. terse_cli-0.1.0/shared/ToolsTypes.ts +21 -0
  23. terse_cli-0.1.0/shared/types.ts +884 -0
  24. terse_cli-0.1.0/src/terse_cli/__init__.py +3 -0
  25. terse_cli-0.1.0/src/terse_cli/__main__.py +4 -0
  26. terse_cli-0.1.0/src/terse_cli/_debug.py +25 -0
  27. terse_cli-0.1.0/src/terse_cli/_generate.py +669 -0
  28. terse_cli-0.1.0/src/terse_cli/_http.py +181 -0
  29. terse_cli-0.1.0/src/terse_cli/_loader.py +134 -0
  30. terse_cli-0.1.0/src/terse_cli/_package.py +197 -0
  31. terse_cli-0.1.0/src/terse_cli/_project.py +187 -0
  32. terse_cli-0.1.0/src/terse_cli/_session.py +179 -0
  33. terse_cli-0.1.0/src/terse_cli/_ui.py +85 -0
  34. terse_cli-0.1.0/src/terse_cli/cli.py +26 -0
  35. terse_cli-0.1.0/src/terse_cli/commands/__init__.py +17 -0
  36. terse_cli-0.1.0/src/terse_cli/commands/deploy.py +94 -0
  37. terse_cli-0.1.0/src/terse_cli/commands/generate.py +32 -0
  38. terse_cli-0.1.0/src/terse_cli/commands/init.py +164 -0
  39. terse_cli-0.1.0/src/terse_cli/commands/integrate.py +24 -0
  40. terse_cli-0.1.0/src/terse_cli/commands/run.py +83 -0
  41. terse_cli-0.1.0/src/terse_cli/commands/test.py +92 -0
  42. terse_cli-0.1.0/src/terse_cli/templates/.python-version.tmpl +1 -0
  43. terse_cli-0.1.0/src/terse_cli/templates/README.md.tmpl +25 -0
  44. terse_cli-0.1.0/src/terse_cli/templates/env.example.tmpl +1 -0
  45. terse_cli-0.1.0/src/terse_cli/templates/gitignore.tmpl +3 -0
  46. terse_cli-0.1.0/src/terse_cli/templates/pyproject.toml.tmpl +15 -0
  47. terse_cli-0.1.0/src/terse_cli/templates/src/main.py.tmpl +18 -0
  48. terse_cli-0.1.0/tests/test_init_and_generate.py +319 -0
  49. terse_cli-0.1.0/tests/test_runtime_commands.py +595 -0
  50. terse_cli-0.1.0/tests/test_session.py +22 -0
@@ -0,0 +1,30 @@
1
+ /node_modules
2
+ /backend/node_modules
3
+ /backend/dist
4
+ /packages/terse-sdk/node_modules
5
+ /packages/terse-sdk/dist
6
+ /packages/terse-sdk/src/shared
7
+ /packages/terse-cli/node_modules
8
+ /packages/terse-cli/dist
9
+ .pnpm-store/
10
+
11
+ # Python SDK artifacts
12
+ __pycache__/
13
+ *.py[cod]
14
+ .pytest_cache/
15
+ .mypy_cache/
16
+ .ruff_cache/
17
+ .tox/
18
+ .coverage
19
+ .coverage.*
20
+ htmlcov/
21
+ .venv/
22
+ venv/
23
+ *.egg-info/
24
+ pip-wheel-metadata/
25
+ /packages/terse-python-sdk/build/
26
+ /packages/terse-python-sdk/dist/
27
+ /packages/terse-python-sdk/shared/
28
+ /packages/terse-python-cli/build/
29
+ /packages/terse-python-cli/dist/
30
+ /packages/terse-python-cli/shared/
@@ -0,0 +1,129 @@
1
+ Metadata-Version: 2.4
2
+ Name: terse-cli
3
+ Version: 0.1.0
4
+ Summary: Python CLI for scaffolding and managing Terse projects.
5
+ Project-URL: Homepage, https://useterse.ai
6
+ Author: Terse
7
+ Keywords: agents,ai,automation,cli,terse
8
+ Classifier: Development Status :: 3 - Alpha
9
+ Classifier: Environment :: Console
10
+ Classifier: Intended Audience :: Developers
11
+ Classifier: Programming Language :: Python :: 3
12
+ Classifier: Programming Language :: Python :: 3.11
13
+ Classifier: Programming Language :: Python :: 3.12
14
+ Classifier: Programming Language :: Python :: 3.13
15
+ Classifier: Topic :: Software Development :: Build Tools
16
+ Classifier: Topic :: Software Development :: Code Generators
17
+ Requires-Python: >=3.11
18
+ Requires-Dist: click>=8.3.1
19
+ Requires-Dist: httpx>=0.28.1
20
+ Requires-Dist: jinja2>=3.1.6
21
+ Requires-Dist: pathspec>=1.0.4
22
+ Requires-Dist: python-dotenv>=1.2.2
23
+ Requires-Dist: questionary>=2.1.1
24
+ Requires-Dist: rich>=14.3.3
25
+ Requires-Dist: terse-sdk<0.2.0,>=0.1.0
26
+ Description-Content-Type: text/markdown
27
+
28
+ # terse-cli
29
+
30
+ Python CLI for scaffolding, generating, testing, and deploying [Terse](https://useterse.ai) jobs.
31
+
32
+ ## Installation
33
+
34
+ ```bash
35
+ python -m pip install terse-cli
36
+ ```
37
+
38
+ The CLI installs the published `terse-sdk` automatically.
39
+
40
+ ## Requirements
41
+
42
+ - Python `>=3.11`
43
+ - [`uv`](https://docs.astral.sh/uv/) for working with scaffolded projects
44
+
45
+ The CLI itself can be installed with `pip`, but the generated project scaffold uses `uv sync` and `uv run`.
46
+
47
+ ## Quick Start
48
+
49
+ ```bash
50
+ terse init my-terse-job
51
+ cd my-terse-job
52
+ uv sync
53
+ terse test
54
+ ```
55
+
56
+ If you connect integrations later, regenerate the project helpers:
57
+
58
+ ```bash
59
+ terse generate
60
+ ```
61
+
62
+ ## Commands
63
+
64
+ - `terse init [PROJECT_NAME]`
65
+ - `terse generate`
66
+ - `terse integrate`
67
+ - `terse run [JOB_NAME] --event ... --event-file ...`
68
+ - `terse test [JOB_NAME]`
69
+ - `terse deploy`
70
+
71
+ ## Supported Generated Helpers
72
+
73
+ The current Python codegen surface is intentionally small:
74
+
75
+ - `Schedule.cron(...)`
76
+ - `Attio.skill(...)`
77
+ - `Snowflake.skill(...)`
78
+ - deterministic wrappers on `agent.tools.attio` and `agent.tools.snowflake`
79
+
80
+ `terse generate` writes these helpers into `src/terse_generated.py` inside your project.
81
+
82
+ For example, after generating Snowflake helpers and registering `skills=[Snowflake.skill()]`, a job can call:
83
+
84
+ ```python
85
+ from terse_sdk import CronJobInputEvent
86
+ from terse_generated import TerseAgent
87
+
88
+ def handle(event: CronJobInputEvent, agent: TerseAgent) -> None:
89
+ result = agent.tools.snowflake.execute_query(query="select current_date()")
90
+ print(result.rowCount)
91
+ ```
92
+
93
+ ## Environment Variables
94
+
95
+ - `TERSE_API_KEY`: required for `terse generate`, `terse deploy`, and any agent/tool calls made by your job
96
+ - `TERSE_BACKEND_URL`: optional backend override for local development
97
+ - `TERSE_FRONTEND_URL`: optional frontend override for local development
98
+
99
+ ## Typical Workflow
100
+
101
+ ```bash
102
+ terse init my-terse-job
103
+ cd my-terse-job
104
+ uv sync
105
+ terse test
106
+ terse deploy
107
+ ```
108
+
109
+ To run a job against a serialized event:
110
+
111
+ ```bash
112
+ terse run --event '{"integrationType":"cron_job","eventType":"manual","formattedContent":"Manual trigger","debugLog":"Manual trigger"}'
113
+ ```
114
+
115
+ ## Source
116
+
117
+ - Homepage: [useterse.ai](https://useterse.ai)
118
+ - Repository: [github.com/TerseAI/Terse](https://github.com/TerseAI/Terse)
119
+ - Issues: [github.com/TerseAI/Terse/issues](https://github.com/TerseAI/Terse/issues)
120
+
121
+ ## Development
122
+
123
+ If you are working on the CLI itself from the monorepo:
124
+
125
+ ```bash
126
+ npm run python:setup
127
+ npm run python:check
128
+ npm run python:build
129
+ ```
@@ -0,0 +1,102 @@
1
+ # terse-cli
2
+
3
+ Python CLI for scaffolding, generating, testing, and deploying [Terse](https://useterse.ai) jobs.
4
+
5
+ ## Installation
6
+
7
+ ```bash
8
+ python -m pip install terse-cli
9
+ ```
10
+
11
+ The CLI installs the published `terse-sdk` automatically.
12
+
13
+ ## Requirements
14
+
15
+ - Python `>=3.11`
16
+ - [`uv`](https://docs.astral.sh/uv/) for working with scaffolded projects
17
+
18
+ The CLI itself can be installed with `pip`, but the generated project scaffold uses `uv sync` and `uv run`.
19
+
20
+ ## Quick Start
21
+
22
+ ```bash
23
+ terse init my-terse-job
24
+ cd my-terse-job
25
+ uv sync
26
+ terse test
27
+ ```
28
+
29
+ If you connect integrations later, regenerate the project helpers:
30
+
31
+ ```bash
32
+ terse generate
33
+ ```
34
+
35
+ ## Commands
36
+
37
+ - `terse init [PROJECT_NAME]`
38
+ - `terse generate`
39
+ - `terse integrate`
40
+ - `terse run [JOB_NAME] --event ... --event-file ...`
41
+ - `terse test [JOB_NAME]`
42
+ - `terse deploy`
43
+
44
+ ## Supported Generated Helpers
45
+
46
+ The current Python codegen surface is intentionally small:
47
+
48
+ - `Schedule.cron(...)`
49
+ - `Attio.skill(...)`
50
+ - `Snowflake.skill(...)`
51
+ - deterministic wrappers on `agent.tools.attio` and `agent.tools.snowflake`
52
+
53
+ `terse generate` writes these helpers into `src/terse_generated.py` inside your project.
54
+
55
+ For example, after generating Snowflake helpers and registering `skills=[Snowflake.skill()]`, a job can call:
56
+
57
+ ```python
58
+ from terse_sdk import CronJobInputEvent
59
+ from terse_generated import TerseAgent
60
+
61
+ def handle(event: CronJobInputEvent, agent: TerseAgent) -> None:
62
+ result = agent.tools.snowflake.execute_query(query="select current_date()")
63
+ print(result.rowCount)
64
+ ```
65
+
66
+ ## Environment Variables
67
+
68
+ - `TERSE_API_KEY`: required for `terse generate`, `terse deploy`, and any agent/tool calls made by your job
69
+ - `TERSE_BACKEND_URL`: optional backend override for local development
70
+ - `TERSE_FRONTEND_URL`: optional frontend override for local development
71
+
72
+ ## Typical Workflow
73
+
74
+ ```bash
75
+ terse init my-terse-job
76
+ cd my-terse-job
77
+ uv sync
78
+ terse test
79
+ terse deploy
80
+ ```
81
+
82
+ To run a job against a serialized event:
83
+
84
+ ```bash
85
+ terse run --event '{"integrationType":"cron_job","eventType":"manual","formattedContent":"Manual trigger","debugLog":"Manual trigger"}'
86
+ ```
87
+
88
+ ## Source
89
+
90
+ - Homepage: [useterse.ai](https://useterse.ai)
91
+ - Repository: [github.com/TerseAI/Terse](https://github.com/TerseAI/Terse)
92
+ - Issues: [github.com/TerseAI/Terse/issues](https://github.com/TerseAI/Terse/issues)
93
+
94
+ ## Development
95
+
96
+ If you are working on the CLI itself from the monorepo:
97
+
98
+ ```bash
99
+ npm run python:setup
100
+ npm run python:check
101
+ npm run python:build
102
+ ```
@@ -0,0 +1,45 @@
1
+ [project]
2
+ name = "terse-cli"
3
+ version = "0.1.0"
4
+ description = "Python CLI for scaffolding and managing Terse projects."
5
+ readme = "README.md"
6
+ requires-python = ">=3.11"
7
+ authors = [{ name = "Terse" }]
8
+ keywords = ["terse", "ai", "agents", "automation", "cli"]
9
+ classifiers = [
10
+ "Development Status :: 3 - Alpha",
11
+ "Environment :: Console",
12
+ "Intended Audience :: Developers",
13
+ "Programming Language :: Python :: 3",
14
+ "Programming Language :: Python :: 3.11",
15
+ "Programming Language :: Python :: 3.12",
16
+ "Programming Language :: Python :: 3.13",
17
+ "Topic :: Software Development :: Build Tools",
18
+ "Topic :: Software Development :: Code Generators",
19
+ ]
20
+ dependencies = [
21
+ "click>=8.3.1",
22
+ "httpx>=0.28.1",
23
+ "Jinja2>=3.1.6",
24
+ "pathspec>=1.0.4",
25
+ "python-dotenv>=1.2.2",
26
+ "questionary>=2.1.1",
27
+ "rich>=14.3.3",
28
+ "terse-sdk>=0.1.0,<0.2.0",
29
+ ]
30
+
31
+ [project.urls]
32
+ Homepage = "https://useterse.ai"
33
+
34
+ [project.scripts]
35
+ terse = "terse_cli.cli:cli"
36
+
37
+ [build-system]
38
+ requires = ["hatchling>=1.29.0"]
39
+ build-backend = "hatchling.build"
40
+
41
+ [tool.uv.sources]
42
+ terse-sdk = { workspace = true }
43
+
44
+ [tool.hatch.build.targets.wheel]
45
+ packages = ["src/terse_cli"]
@@ -0,0 +1,350 @@
1
+ /**
2
+ * API route path constants
3
+ *
4
+ * These constants standardize API route paths across frontend and backend,
5
+ * preventing magic strings and making refactoring easier.
6
+ *
7
+ * Dynamic routes use route objects with both Express patterns and URL builders
8
+ * to ensure frontend and backend stay in sync.
9
+ */
10
+
11
+ // Type definitions for route objects
12
+
13
+ export const ApiRoutes = {
14
+ // Authentication routes
15
+ AUTH: {
16
+ ME: "/me",
17
+ LOGIN: "/login",
18
+ LOGIN_URL: "/login/url",
19
+ LOGOUT: "/logout",
20
+ LOGOUT_URL: "/logout/url",
21
+ GITHUB_APP_CALLBACK: "/auth/github-app/callback",
22
+ WORKOS_CALLBACK: "/auth/workos/callback"
23
+ },
24
+
25
+ WORKOS: {
26
+ WIDGET_TOKEN: "/auth/workos/widget-token"
27
+ },
28
+
29
+ ORGANIZATIONS: {
30
+ CREATE: "/organizations",
31
+ GET_CURRENT: "/organizations/current",
32
+ LIST: "/organizations",
33
+ SWITCH: "/organizations/switch",
34
+ UPDATE: "/organizations",
35
+ LOGO_UPLOAD_URL: "/organizations/logo/upload-url",
36
+ LOGO: {
37
+ pattern: "/organizations/:organizationId/logo",
38
+ build: (organizationId: string) => `/organizations/${encodeURIComponent(organizationId)}/logo`,
39
+ params: { organizationId: "string" } as const
40
+ }
41
+ },
42
+
43
+ // Stats routes
44
+ STATS: "/stats",
45
+
46
+ // Run history routes
47
+ RUN_HISTORY: {
48
+ ALL: "/run-history",
49
+ ACTIONS: "/run-history/actions",
50
+ BY_AGENT_ID: {
51
+ pattern: "/run-history/:agentId",
52
+ build: (agentId: string) => `/run-history/${encodeURIComponent(agentId)}`,
53
+ params: { agentId: "string" } as const
54
+ },
55
+ CHAT_BY_RUN_ID: {
56
+ pattern: "/run-history/:runId/chat",
57
+ build: (runId: string) => `/run-history/${encodeURIComponent(runId)}/chat`,
58
+ params: { runId: "string" } as const
59
+ }
60
+ },
61
+
62
+ // Session routes
63
+ SESSION: {
64
+ TOKEN: "/session/token"
65
+ },
66
+
67
+ // GitHub routes
68
+ GITHUB: {
69
+ INTEGRATIONS: "/github/integrations",
70
+ INSTALLATION_URL: "/github/installation-url",
71
+ GET_REPOSITORIES_FOR_INTEGRATION: "/github/get-repositories-for-integration",
72
+ INSTALLATION_CALLBACK: "/github/installation-callback",
73
+ INSTALLATION_DELETED: "/github/installation-deleted",
74
+ UNIFIED_EVENT: "/github/unified-event"
75
+ },
76
+
77
+ // Atlassian/Jira routes
78
+ ATLASSIAN: {
79
+ INTEGRATIONS: "/atlassian/integrations",
80
+ OAUTH_CALLBACK: "/atlassian/oauth/callback"
81
+ },
82
+
83
+ JIRA: {
84
+ RESOURCES: "/jira/resources",
85
+ GET_API_KEY: "/jira/get-api-key",
86
+ SET_API_KEY: "/jira/set-api-key",
87
+ VALIDATE_AND_FETCH_PROJECTS: "/jira/validate-and-fetch-projects",
88
+ DELETE_CREDENTIALS: "/jira/delete-credentials"
89
+ },
90
+
91
+ // Confluence routes
92
+ CONFLUENCE: {
93
+ INTEGRATIONS: "/confluence/integrations",
94
+ RESOURCES: "/confluence/resources"
95
+ },
96
+
97
+ // Gmail routes
98
+ GMAIL: {
99
+ INTEGRATIONS: "/gmail/integrations",
100
+ CALLBACK: "/gmail/callback",
101
+ DELETE_INTEGRATION: "/gmail/delete-integration"
102
+ },
103
+
104
+ // Notion routes
105
+ NOTION: {
106
+ INTEGRATIONS: "/notion/integrations",
107
+ OAUTH_CALLBACK: "/notion/oauth/callback",
108
+ RESOURCES: "/notion/resources",
109
+ DELETE_INTEGRATION: "/notion/delete-integration"
110
+ },
111
+
112
+ // Figma routes
113
+ FIGMA: {
114
+ INTEGRATIONS: "/figma/integrations",
115
+ OAUTH_CALLBACK: "/figma/oauth/callback"
116
+ },
117
+
118
+ // Linear routes
119
+ LINEAR: {
120
+ OAUTH_CALLBACK: "/linear/oauth/callback",
121
+ WEBHOOK: "/linear/webhook",
122
+ INTEGRATIONS: "/linear/integrations",
123
+ TEAMS: "/linear/teams"
124
+ },
125
+
126
+ // Slack routes
127
+ SLACK: {
128
+ INTEGRATIONS: "/slack/integrations",
129
+ GET_CURRENT_INTEGRATION: "/slack/get-current-integration",
130
+ OAUTH_CALLBACK: "/slack/oauth-callback",
131
+ CHANNELS: "/slack/channels",
132
+ USERS: "/slack/users",
133
+ EVENTS: "/slack/events"
134
+ },
135
+
136
+ // Posthog routes
137
+ POSTHOG: {
138
+ INTEGRATIONS: "/posthog/integrations",
139
+ PROJECTS: "/posthog/projects"
140
+ },
141
+
142
+ // LaunchDarkly routes
143
+ LAUNCHDARKLY: {
144
+ INTEGRATIONS: "/launchdarkly/integrations",
145
+ PROJECTS_BY_INTEGRATION_ID: {
146
+ pattern: "/launchdarkly/integrations/:integrationId/projects",
147
+ build: (integrationId: string) => `/launchdarkly/integrations/${encodeURIComponent(integrationId)}/projects`,
148
+ params: { integrationId: "string" } as const
149
+ },
150
+ ENVIRONMENTS_BY_INTEGRATION_AND_PROJECT: {
151
+ pattern: "/launchdarkly/integrations/:integrationId/projects/:projectKey/environments",
152
+ build: (integrationId: string, projectKey: string) => `/launchdarkly/integrations/${encodeURIComponent(integrationId)}/projects/${encodeURIComponent(projectKey)}/environments`,
153
+ params: { integrationId: "string", projectKey: "string" } as const
154
+ }
155
+ },
156
+
157
+ // Datadog routes
158
+ DATADOG: {
159
+ INTEGRATIONS: "/datadog/integrations",
160
+ INDEXES: "/datadog/indexes"
161
+ },
162
+
163
+ // WorkOS Integration routes (customer's own WorkOS account)
164
+ WORKOS_INTEGRATION: {
165
+ INTEGRATIONS: "/workos-integration/integrations",
166
+ WEBHOOK_SECRET: "/workos-integration/webhook-secret"
167
+ },
168
+
169
+ // Snowflake routes
170
+ SNOWFLAKE: {
171
+ INTEGRATIONS: "/snowflake/integrations"
172
+ },
173
+
174
+ // Attio routes
175
+ ATTIO: {
176
+ INTEGRATIONS: "/attio/integrations",
177
+ OAUTH_CALLBACK: "/attio/oauth/callback",
178
+ OBJECTS: {
179
+ pattern: "/attio/integrations/:integrationId/objects",
180
+ build: (integrationId: string) => `/attio/integrations/${encodeURIComponent(integrationId)}/objects`,
181
+ params: { integrationId: "string" } as const
182
+ }
183
+ },
184
+
185
+ // Agents routes
186
+ AGENTS: {
187
+ LIST: "/agents",
188
+ RECENT: "/agents/recent",
189
+ BY_ID: {
190
+ pattern: "/agents/:id",
191
+ build: (id: string) => `/agents/${encodeURIComponent(id)}`,
192
+ params: { id: "string" } as const
193
+ }
194
+ },
195
+
196
+ IMPROVEMENTS: {
197
+ BY_AGENT_ID: {
198
+ pattern: "/agents/:agentId/improvements",
199
+ build: (agentId: string) => `/agents/${encodeURIComponent(agentId)}/improvements`,
200
+ params: { agentId: "string" } as const
201
+ },
202
+ APPLY: {
203
+ pattern: "/agents/:agentId/improvements/:id/apply",
204
+ build: (agentId: string, id: string) => `/agents/${encodeURIComponent(agentId)}/improvements/${encodeURIComponent(id)}/apply`,
205
+ params: { agentId: "string", id: "string" } as const
206
+ },
207
+ DISMISS: {
208
+ pattern: "/agents/:agentId/improvements/:id/dismiss",
209
+ build: (agentId: string, id: string) => `/agents/${encodeURIComponent(agentId)}/improvements/${encodeURIComponent(id)}/dismiss`,
210
+ params: { agentId: "string", id: "string" } as const
211
+ },
212
+ UNDO_DISMISS: {
213
+ pattern: "/agents/:agentId/improvements/:id/undo-dismiss",
214
+ build: (agentId: string, id: string) => `/agents/${encodeURIComponent(agentId)}/improvements/${encodeURIComponent(id)}/undo-dismiss`,
215
+ params: { agentId: "string", id: "string" } as const
216
+ },
217
+ TOGGLE_ENABLED: {
218
+ pattern: "/agents/:agentId/improvements-enabled",
219
+ build: (agentId: string) => `/agents/${encodeURIComponent(agentId)}/improvements-enabled`,
220
+ params: { agentId: "string" } as const
221
+ }
222
+ },
223
+
224
+ // Templates routes
225
+ TEMPLATES: "/templates",
226
+ PUBLIC: {
227
+ TEMPLATES: "/public/templates"
228
+ },
229
+
230
+ // Tools routes
231
+ TOOLS: {
232
+ THAT_REQUIRE_APPROVALS: "/tools/that-require-approvals"
233
+ },
234
+
235
+ // Integrations routes
236
+ INTEGRATIONS: {
237
+ INSTALLATION_DETAILS_BY_TYPE: {
238
+ pattern: "/integrations/:integrationType/installation-details",
239
+ build: (integrationType: string) => `/integrations/${encodeURIComponent(integrationType)}/installation-details`,
240
+ params: { integrationType: "string" } as const
241
+ },
242
+ LIST: "/integrations",
243
+ ACTIVE: "/integrations/active"
244
+ },
245
+
246
+ // Notification destinations routes
247
+ NOTIFICATION_DESTINATIONS: {
248
+ LIST: "/notification-destinations",
249
+ BY_ID: {
250
+ pattern: "/notification-destinations/:id",
251
+ build: (id: string) => `/notification-destinations/${encodeURIComponent(id)}`,
252
+ params: { id: "string" } as const
253
+ }
254
+ },
255
+
256
+ // API Tokens routes
257
+ API_TOKENS: {
258
+ LIST: "/api-tokens",
259
+ BY_ID: {
260
+ pattern: "/api-tokens/:id",
261
+ build: (id: string) => `/api-tokens/${encodeURIComponent(id)}`,
262
+ params: { id: "string" } as const
263
+ }
264
+ },
265
+
266
+ // SDK routes (authenticated via API tokens)
267
+ SDK: {
268
+ ME: "/sdk/me",
269
+ SAMPLE_EVENTS: "/sdk/sample-events",
270
+ TOOL_EXECUTE: "/sdk/tool-execute",
271
+ TOOL_DEFINITIONS: "/sdk/tool-definitions",
272
+ AGENT_RUN: "/sdk/agent-run",
273
+ SESSION_EVENTS: "/sdk/session-events",
274
+ DEPLOY: "/sdk/deploy"
275
+ },
276
+
277
+ NOTIFICATION_SETTINGS: "/notification-settings",
278
+
279
+ SENT_NOTIFICATIONS: {
280
+ LIST: "/sent-notifications"
281
+ },
282
+
283
+ PENDING_APPROVALS: {
284
+ LIST: "/pending-approvals"
285
+ },
286
+
287
+ // Webhooks routes
288
+ WEBHOOKS: {
289
+ GMAIL: "/webhooks/gmail",
290
+ FIGMA: "/webhooks/figma",
291
+ WORKOS: "/webhooks/workos",
292
+ JIRA_BY_ACCOUNT_ID: {
293
+ pattern: "/webhooks/jira/:accountId",
294
+ build: (accountId: string) => `/webhooks/jira/${encodeURIComponent(accountId)}`,
295
+ params: { accountId: "string" } as const
296
+ },
297
+ LINEAR_BY_USER_ID: {
298
+ pattern: "/webhooks/linear/:userId",
299
+ build: (userId: string) => `/webhooks/linear/${encodeURIComponent(userId)}`,
300
+ params: { userId: "string" } as const
301
+ },
302
+ SCHEDULE_BY_INPUT_ID: {
303
+ pattern: "/webhooks/schedule/:inputId",
304
+ build: (inputId: string) => `/webhooks/schedule/${encodeURIComponent(inputId)}`,
305
+ params: { inputId: "string" } as const
306
+ },
307
+ WORKOS_TRIGGER_BY_INTEGRATION_ID: {
308
+ pattern: "/webhooks/workos-trigger/:integrationId",
309
+ build: (integrationId: string) => `/webhooks/workos-trigger/${encodeURIComponent(integrationId)}`,
310
+ params: { integrationId: "string" } as const
311
+ }
312
+ },
313
+
314
+ // Schedule routes
315
+ SCHEDULE: {
316
+ TRIGGER_BY_INPUT_ID: {
317
+ pattern: "/schedule/trigger/:inputId",
318
+ build: (inputId: string) => `/schedule/trigger/${encodeURIComponent(inputId)}`,
319
+ params: { inputId: "string" } as const
320
+ },
321
+ TRIGGER_WITH_EVENT: {
322
+ pattern: "/schedule/trigger-with-event/:automationId",
323
+ build: (automationId: string) => `/schedule/trigger-with-event/${encodeURIComponent(automationId)}`,
324
+ params: { automationId: "string" } as const
325
+ }
326
+ },
327
+
328
+ // Refresh tokens route
329
+ REFRESH_TOKENS: "/refresh-tokens",
330
+ REVIEW_AGENTS: "/review-agents",
331
+
332
+ // Users routes
333
+ USERS: {
334
+ CREATE: "/users",
335
+ BY_ID: {
336
+ pattern: "/users/:id",
337
+ build: (id: string) => `/users/${encodeURIComponent(id)}`,
338
+ params: { id: "string" } as const
339
+ }
340
+ },
341
+
342
+ // Builder chat routes
343
+ BUILDER_CHAT: {
344
+ HISTORY_BY_SESSION_ID: {
345
+ pattern: "/builder-chat/:sessionId/history",
346
+ build: (sessionId: string) => `/builder-chat/${encodeURIComponent(sessionId)}/history`,
347
+ params: { sessionId: "string" } as const
348
+ }
349
+ }
350
+ } as const
@@ -0,0 +1,36 @@
1
+ import { IntegrationType } from "./Integrations"
2
+
3
+ export type ApprovalActionType = "open_run_history" | "approve_action" | "reject_action"
4
+ export type ApprovalRequestStatus = "pending" | "in_progress" | "completed"
5
+ export type ApprovalRequestFilter = ApprovalRequestStatus | "all"
6
+
7
+ export type ApprovalAction = {
8
+ type: ApprovalActionType
9
+ label: string
10
+ deepLink: string
11
+ }
12
+
13
+ export type ApprovalRequest = {
14
+ id: string
15
+ icon: IntegrationType
16
+ title: string
17
+ subheader: string
18
+ timestamp: string
19
+ status: ApprovalRequestStatus
20
+ actions: ApprovalAction[]
21
+ runId: string
22
+ agentId: string
23
+ }
24
+
25
+ export type GetPendingApprovalsResponse = {
26
+ items: ApprovalRequest[]
27
+ }
28
+
29
+ export function parseDeepLink(deepLink: string): { type: string; params: string[] } {
30
+ const parts = deepLink.split("|")
31
+ return { type: parts[0], params: parts.slice(1) }
32
+ }
33
+
34
+ export function encodeDeepLink(type: ApprovalActionType, ...params: string[]): string {
35
+ return [type, ...params].join("|")
36
+ }