source dump of claude code
26
fork

Configure Feed

Select the types of activity you want to include in your feed.

at main 161 lines 4.7 kB view raw
1import axios from 'axios' 2import { z } from 'zod/v4' 3import { getOauthConfig } from '../../constants/oauth.js' 4import { getFeatureValue_CACHED_MAY_BE_STALE } from '../../services/analytics/growthbook.js' 5import { getOrganizationUUID } from '../../services/oauth/client.js' 6import { isPolicyAllowed } from '../../services/policyLimits/index.js' 7import type { ToolUseContext } from '../../Tool.js' 8import { buildTool, type ToolDef } from '../../Tool.js' 9import { 10 checkAndRefreshOAuthTokenIfNeeded, 11 getClaudeAIOAuthTokens, 12} from '../../utils/auth.js' 13import { lazySchema } from '../../utils/lazySchema.js' 14import { jsonStringify } from '../../utils/slowOperations.js' 15import { DESCRIPTION, PROMPT, REMOTE_TRIGGER_TOOL_NAME } from './prompt.js' 16import { renderToolResultMessage, renderToolUseMessage } from './UI.js' 17 18const inputSchema = lazySchema(() => 19 z.strictObject({ 20 action: z.enum(['list', 'get', 'create', 'update', 'run']), 21 trigger_id: z 22 .string() 23 .regex(/^[\w-]+$/) 24 .optional() 25 .describe('Required for get, update, and run'), 26 body: z 27 .record(z.string(), z.unknown()) 28 .optional() 29 .describe('JSON body for create and update'), 30 }), 31) 32type InputSchema = ReturnType<typeof inputSchema> 33export type Input = z.infer<InputSchema> 34 35const outputSchema = lazySchema(() => 36 z.object({ 37 status: z.number(), 38 json: z.string(), 39 }), 40) 41type OutputSchema = ReturnType<typeof outputSchema> 42export type Output = z.infer<OutputSchema> 43 44const TRIGGERS_BETA = 'ccr-triggers-2026-01-30' 45 46export const RemoteTriggerTool = buildTool({ 47 name: REMOTE_TRIGGER_TOOL_NAME, 48 searchHint: 'manage scheduled remote agent triggers', 49 maxResultSizeChars: 100_000, 50 shouldDefer: true, 51 get inputSchema(): InputSchema { 52 return inputSchema() 53 }, 54 get outputSchema(): OutputSchema { 55 return outputSchema() 56 }, 57 isEnabled() { 58 return ( 59 getFeatureValue_CACHED_MAY_BE_STALE('tengu_surreal_dali', false) && 60 isPolicyAllowed('allow_remote_sessions') 61 ) 62 }, 63 isConcurrencySafe() { 64 return true 65 }, 66 isReadOnly(input: Input) { 67 return input.action === 'list' || input.action === 'get' 68 }, 69 toAutoClassifierInput(input: Input) { 70 return `RemoteTrigger ${input.action}${input.trigger_id ? ` ${input.trigger_id}` : ''}` 71 }, 72 async description() { 73 return DESCRIPTION 74 }, 75 async prompt() { 76 return PROMPT 77 }, 78 async call(input: Input, context: ToolUseContext) { 79 await checkAndRefreshOAuthTokenIfNeeded() 80 const accessToken = getClaudeAIOAuthTokens()?.accessToken 81 if (!accessToken) { 82 throw new Error( 83 'Not authenticated with a claude.ai account. Run /login and try again.', 84 ) 85 } 86 const orgUUID = await getOrganizationUUID() 87 if (!orgUUID) { 88 throw new Error('Unable to resolve organization UUID.') 89 } 90 91 const base = `${getOauthConfig().BASE_API_URL}/v1/code/triggers` 92 const headers = { 93 Authorization: `Bearer ${accessToken}`, 94 'Content-Type': 'application/json', 95 'anthropic-version': '2023-06-01', 96 'anthropic-beta': TRIGGERS_BETA, 97 'x-organization-uuid': orgUUID, 98 } 99 100 const { action, trigger_id, body } = input 101 let method: 'GET' | 'POST' 102 let url: string 103 let data: unknown 104 switch (action) { 105 case 'list': 106 method = 'GET' 107 url = base 108 break 109 case 'get': 110 if (!trigger_id) throw new Error('get requires trigger_id') 111 method = 'GET' 112 url = `${base}/${trigger_id}` 113 break 114 case 'create': 115 if (!body) throw new Error('create requires body') 116 method = 'POST' 117 url = base 118 data = body 119 break 120 case 'update': 121 if (!trigger_id) throw new Error('update requires trigger_id') 122 if (!body) throw new Error('update requires body') 123 method = 'POST' 124 url = `${base}/${trigger_id}` 125 data = body 126 break 127 case 'run': 128 if (!trigger_id) throw new Error('run requires trigger_id') 129 method = 'POST' 130 url = `${base}/${trigger_id}/run` 131 data = {} 132 break 133 } 134 135 const res = await axios.request({ 136 method, 137 url, 138 headers, 139 data, 140 timeout: 20_000, 141 signal: context.abortController.signal, 142 validateStatus: () => true, 143 }) 144 145 return { 146 data: { 147 status: res.status, 148 json: jsonStringify(res.data), 149 }, 150 } 151 }, 152 mapToolResultToToolResultBlockParam(output, toolUseID) { 153 return { 154 tool_use_id: toolUseID, 155 type: 'tool_result', 156 content: `HTTP ${output.status}\n${output.json}`, 157 } 158 }, 159 renderToolUseMessage, 160 renderToolResultMessage, 161} satisfies ToolDef<InputSchema, Output>)