refactor: use SkillClient, remove manual auth handling

Replace createEnvConfig/getAccessToken/requestApiWithAutoRefresh
with createSkillClient(). workflow.ts now takes a SkillClient
instead of config+token. Remove EnvConfig extension from types.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
ywkj 2026-03-18 08:25:09 +08:00
parent 56d3051253
commit e7d9e972d4
3 changed files with 29 additions and 129 deletions

View File

@ -1,20 +1,8 @@
import type { EnvConfig, OutputResult } from './types.js'; import type { OutputResult } from './types.js';
import { createEnvConfig as createBaseEnvConfig, getAccessToken } from '@clawd/auth-runtime'; import { createSkillClient } from '@clawd/auth-runtime';
import { normalizeQuery, resolveExpansion } from './expansion.js'; import { normalizeQuery, resolveExpansion } from './expansion.js';
import { startWorkflow } from './workflow.js'; import { startWorkflow } from './workflow.js';
/**
* Create client-finder specific environment configuration
* Extends the shared auth config with skill-specific fields
*/
function createEnvConfig(): EnvConfig {
const baseConfig = createBaseEnvConfig();
return {
...baseConfig,
queryExpansionJson: process.env.QUERY_EXPANSION_JSON || '',
};
}
/** /**
* Main entry point for client-finder skill * Main entry point for client-finder skill
*/ */
@ -23,8 +11,6 @@ export async function runClientFinder(
country: string, country: string,
dryRun: boolean = false, dryRun: boolean = false,
): Promise<OutputResult> { ): Promise<OutputResult> {
const config = createEnvConfig();
// Validate query // Validate query
if (!query) { if (!query) {
return createFailedResult('', 'missing query argument'); return createFailedResult('', 'missing query argument');
@ -36,11 +22,8 @@ export async function runClientFinder(
const countryLower = country.toLowerCase(); const countryLower = country.toLowerCase();
// Resolve expansion // Resolve expansion
const expansion = resolveExpansion( const queryExpansionJson = process.env.QUERY_EXPANSION_JSON || '';
rawQuery, const expansion = resolveExpansion(rawQuery, countryUpper, queryExpansionJson);
countryUpper,
config.queryExpansionJson,
);
let expandedQueries = expansion.expandedQueries; let expandedQueries = expansion.expandedQueries;
let primaryQuery = expansion.primaryQuery; let primaryQuery = expansion.primaryQuery;
@ -60,14 +43,8 @@ export async function runClientFinder(
} else { } else {
expansionError = expansionError || 'query expansion failed: primary query is empty'; expansionError = expansionError || 'query expansion failed: primary query is empty';
return createFailedResult( return createFailedResult(
rawQuery, rawQuery, expansionError, expandedQueries, primaryQuery,
expansionError, expansionStatus, expansionSource, expansionError, usedFallbackQuery,
expandedQueries,
primaryQuery,
expansionStatus,
expansionSource,
expansionError,
usedFallbackQuery,
); );
} }
} }
@ -76,104 +53,51 @@ export async function runClientFinder(
if (!primaryQuery) { if (!primaryQuery) {
expansionError = expansionError || 'query expansion failed: primary query is empty'; expansionError = expansionError || 'query expansion failed: primary query is empty';
return createFailedResult( return createFailedResult(
rawQuery, rawQuery, expansionError, expandedQueries, primaryQuery,
expansionError, expansionStatus, expansionSource, expansionError, usedFallbackQuery,
expandedQueries,
primaryQuery,
expansionStatus,
expansionSource,
expansionError,
usedFallbackQuery,
); );
} }
// Dry run mode // Dry run mode
if (dryRun) { if (dryRun) {
return createSuccessResult( return createSuccessResult(
rawQuery, rawQuery, expandedQueries, primaryQuery,
expandedQueries, expansionStatus, expansionSource, expansionError, usedFallbackQuery,
primaryQuery, '', 'dry_run',
expansionStatus,
expansionSource,
expansionError,
usedFallbackQuery,
'',
'dry_run',
); );
} }
// Validate CLIENT_KEY in live mode // Create client (validates CLIENT_KEY)
if (!config.clientKey) { let client;
return createFailedResult(
rawQuery,
'missing required env: CLIENT_KEY',
expandedQueries,
primaryQuery,
expansionStatus,
expansionSource,
expansionError,
usedFallbackQuery,
);
}
// Step 1: Exchange CLIENT_KEY for runtime access token
let accessToken = '';
try { try {
accessToken = await getAccessToken(dryRun, config); client = createSkillClient();
} catch (error) { } catch (error) {
const errorMsg = error instanceof Error ? error.message : 'failed to exchange skill session token';
return createFailedResult( return createFailedResult(
rawQuery, rawQuery, error instanceof Error ? error.message : 'failed to create client',
errorMsg, expandedQueries, primaryQuery,
expandedQueries, expansionStatus, expansionSource, expansionError, usedFallbackQuery,
primaryQuery,
expansionStatus,
expansionSource,
expansionError,
usedFallbackQuery,
); );
} }
// Step 2: Start workflow with runtime access token // Start workflow
const workflowResult = await startWorkflow( const workflowResult = await startWorkflow(client, primaryQuery, countryLower);
config,
dryRun,
accessToken,
primaryQuery,
countryLower,
);
if (!workflowResult.workflowId) { if (!workflowResult.workflowId) {
return createFailedResult( return createFailedResult(
rawQuery, rawQuery, `start failed: ${workflowResult.error}`,
`start failed: ${workflowResult.error}`, expandedQueries, primaryQuery,
expandedQueries, expansionStatus, expansionSource, expansionError, usedFallbackQuery,
primaryQuery,
expansionStatus,
expansionSource,
expansionError,
usedFallbackQuery,
); );
} }
// Step 3: Return accepted immediately // Return accepted immediately
return createSuccessResult( return createSuccessResult(
rawQuery, rawQuery, expandedQueries, primaryQuery,
expandedQueries, expansionStatus, expansionSource, expansionError, usedFallbackQuery,
primaryQuery, '', 'accepted', workflowResult.workflowId,
expansionStatus,
expansionSource,
expansionError,
usedFallbackQuery,
'',
'accepted',
workflowResult.workflowId,
); );
} }
/**
* Create a failed result
*/
function createFailedResult( function createFailedResult(
inputQuery: string, inputQuery: string,
error: string, error: string,
@ -205,9 +129,6 @@ function createFailedResult(
}; };
} }
/**
* Create a success result
*/
function createSuccessResult( function createSuccessResult(
inputQuery: string, inputQuery: string,
expandedQueries: string[], expandedQueries: string[],

View File

@ -1,5 +1,3 @@
import type { EnvConfig as BaseEnvConfig } from '@clawd/auth-runtime';
/** /**
* Query expansion result from LLM or rule-based logic * Query expansion result from LLM or rule-based logic
*/ */
@ -45,10 +43,3 @@ export interface OutputResult {
uniqueContactDomains: number; uniqueContactDomains: number;
} }
/**
* Client-finder specific environment configuration
* Extends the shared auth config with skill-specific fields
*/
export interface EnvConfig extends BaseEnvConfig {
queryExpansionJson: string;
}

View File

@ -1,5 +1,4 @@
import { requestApiWithAutoRefresh } from '@clawd/auth-runtime'; import type { SkillClient } from '@clawd/auth-runtime';
import type { EnvConfig as AuthEnvConfig } from '@clawd/auth-runtime';
import { WorkflowStartResponse } from './types.js'; import { WorkflowStartResponse } from './types.js';
/** /**
@ -18,26 +17,15 @@ export function parseWorkflowId(responseBody: string): string {
* Start cold outreach workflow * Start cold outreach workflow
*/ */
export async function startWorkflow( export async function startWorkflow(
config: AuthEnvConfig, client: SkillClient,
dryRun: boolean,
accessToken: string,
query: string, query: string,
country: string, country: string,
): Promise<{ workflowId: string; error: string }> { ): Promise<{ workflowId: string; error: string }> {
const payload = JSON.stringify({ const result = await client.post('/ecom/cold-outreach/run-flow', {
query, query,
country, country,
}); });
const result = await requestApiWithAutoRefresh(
'POST',
`${config.authBase}/ecom/cold-outreach/run-flow`,
dryRun,
config,
payload,
accessToken,
);
if (result.status < 200 || result.status >= 300) { if (result.status < 200 || result.status >= 300) {
const error = parseError(result.body); const error = parseError(result.body);
return { return {