@socialseal/cli 0.1.2 → 0.1.3
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.
- package/CHANGELOG.md +3 -0
- package/package.json +1 -1
- package/src/index.js +755 -14
package/CHANGELOG.md
CHANGED
|
@@ -2,6 +2,9 @@
|
|
|
2
2
|
|
|
3
3
|
## Unreleased
|
|
4
4
|
|
|
5
|
+
## 0.1.3 - 2026-03-19
|
|
6
|
+
- Republish the current CLI release line after the successful `0.1.2` npm publish, keeping the internal and OSS package versions aligned.
|
|
7
|
+
|
|
5
8
|
## 0.1.2 - 2026-03-18
|
|
6
9
|
- Add `search-journey-run` async CLI ergonomics: `--async` starts the backend async mode, polling is on by default, and `--no-poll` returns the initial `runId` immediately.
|
|
7
10
|
- Add `--poll-interval <ms>` for async `search-journey-run` status polling.
|
package/package.json
CHANGED
package/src/index.js
CHANGED
|
@@ -15,6 +15,7 @@ const DEFAULT_AGENT_IDLE_TIMEOUT_MS = 300000;
|
|
|
15
15
|
const DEFAULT_POLL_INTERVAL_MS = 2000;
|
|
16
16
|
const MAX_TIMEOUT_MS = 900000;
|
|
17
17
|
const LEGACY_ENABLED = process.env.SOCIALSEAL_ENABLE_LEGACY === '1';
|
|
18
|
+
const STATIC_TOOL_REGISTRY_NOTE = 'This registry is shipped with the CLI for stable discovery. It is not live backend enumeration, so environment-specific availability can drift.';
|
|
18
19
|
const EXIT_CODES = {
|
|
19
20
|
OK: 0,
|
|
20
21
|
UNKNOWN: 1,
|
|
@@ -29,18 +30,66 @@ const KNOWN_TOOLS = [
|
|
|
29
30
|
{ name: 'deep-exploration-runs', category: 'agent', description: 'Read or persist deep exploration render runs.' },
|
|
30
31
|
{ name: 'workspace-notes', category: 'agent', description: 'Search, create, update, and pin workspace note memory.' },
|
|
31
32
|
{ name: 'workspace-onboarding', category: 'agent', description: 'Read or update workspace onboarding metadata used by the agent.' },
|
|
32
|
-
{
|
|
33
|
-
|
|
33
|
+
{
|
|
34
|
+
name: 'brand-group-management',
|
|
35
|
+
category: 'brand',
|
|
36
|
+
description: 'Manage brand groups, aliases, competitors, and rule configuration.',
|
|
37
|
+
objectType: 'brand_group',
|
|
38
|
+
transport: 'rest_edge_function',
|
|
39
|
+
workspaceScoped: true,
|
|
40
|
+
knownLocalDevState: 'enabled',
|
|
41
|
+
actionAliases: ['list', 'create', 'update', 'delete', 'add_member', 'remove_member'],
|
|
42
|
+
notes: 'Brand groups are not tracking groups.',
|
|
43
|
+
},
|
|
44
|
+
{
|
|
45
|
+
name: 'enqueue-brand-metrics-backfill',
|
|
46
|
+
category: 'brand',
|
|
47
|
+
description: 'Queue backfill jobs for brand metrics refreshes.',
|
|
48
|
+
objectType: 'brand_metrics_backfill_job',
|
|
49
|
+
transport: 'post_edge_function',
|
|
50
|
+
workspaceScoped: true,
|
|
51
|
+
knownLocalDevState: 'enabled',
|
|
52
|
+
notes: 'Refreshes brand metrics for brands/workspaces. It does not refresh a tracking group by UUID.',
|
|
53
|
+
},
|
|
34
54
|
{ name: 'export-report', category: 'export', description: 'Generate report exports (csv/json/markdown/html/excel_data).' },
|
|
35
|
-
{
|
|
55
|
+
{
|
|
56
|
+
name: 'export_tracking_data',
|
|
57
|
+
category: 'export',
|
|
58
|
+
description: 'Stream tracking exports as CSV for a group or tracking item.',
|
|
59
|
+
objectType: 'tracking_export',
|
|
60
|
+
transport: 'post_edge_function',
|
|
61
|
+
workspaceScoped: true,
|
|
62
|
+
knownLocalDevState: 'disabled_by_default',
|
|
63
|
+
notes: 'group_id expects a numeric tracking_group id, not a brand_group UUID.',
|
|
64
|
+
},
|
|
36
65
|
{ name: 'douyin-geo-api', category: 'search', description: 'Query Douyin search and geo data.' },
|
|
37
66
|
{ name: 'google-ai-search', category: 'search', description: 'Run Google AI search queries and fetch result snapshots.' },
|
|
38
67
|
{ name: 'instagram-geo-api', category: 'search', description: 'Query Instagram search and geo data.' },
|
|
39
68
|
{ name: 'tiktok-geo-api', category: 'search', description: 'Query TikTok search and geo data.' },
|
|
40
69
|
{ name: 'xhs-geo-api', category: 'search', description: 'Query Xiaohongshu search and geo data.' },
|
|
41
70
|
{ name: 'youtube-geo-api', category: 'search', description: 'Query YouTube search and geo data.' },
|
|
42
|
-
{
|
|
43
|
-
|
|
71
|
+
{
|
|
72
|
+
name: 'group-management',
|
|
73
|
+
category: 'tracking',
|
|
74
|
+
description: 'Manage tracking groups and memberships.',
|
|
75
|
+
objectType: 'tracking_group',
|
|
76
|
+
transport: 'rest_edge_function',
|
|
77
|
+
workspaceScoped: true,
|
|
78
|
+
knownLocalDevState: 'disabled_by_default',
|
|
79
|
+
actionAliases: ['list', 'get', 'create', 'update', 'delete', 'refresh', 'list_items'],
|
|
80
|
+
notes: 'REST-style surface under /groups. Use action aliases via `tools call` or raw REST semantics.',
|
|
81
|
+
},
|
|
82
|
+
{
|
|
83
|
+
name: 'tracking',
|
|
84
|
+
category: 'tracking',
|
|
85
|
+
description: 'Manage tracking items.',
|
|
86
|
+
objectType: 'tracking_item',
|
|
87
|
+
transport: 'rest_edge_function',
|
|
88
|
+
workspaceScoped: true,
|
|
89
|
+
knownLocalDevState: 'enabled',
|
|
90
|
+
actionAliases: ['list', 'get', 'create', 'update', 'delete', 'refresh'],
|
|
91
|
+
notes: 'REST-style surface. The CLI normalizes common action payloads for this tool.',
|
|
92
|
+
},
|
|
44
93
|
{ name: 'journey-feedback', category: 'vnext', description: 'Record acceptance or rejection feedback for opportunity bundles.' },
|
|
45
94
|
{ name: 'opportunity-bundle-approve', category: 'vnext', description: 'Approve an opportunity bundle and create tracking coverage.' },
|
|
46
95
|
{ name: 'search-journey-run', category: 'vnext', description: 'Run a search journey for a subject across supported platforms.' },
|
|
@@ -290,10 +339,660 @@ function mergeWorkspaceIdIntoPayload(payload, workspaceId) {
|
|
|
290
339
|
return { ...payload, workspaceId };
|
|
291
340
|
}
|
|
292
341
|
|
|
342
|
+
function hasOwn(value, key) {
|
|
343
|
+
return Boolean(value) && Object.prototype.hasOwnProperty.call(value, key);
|
|
344
|
+
}
|
|
345
|
+
|
|
346
|
+
function firstDefined(source, keys) {
|
|
347
|
+
if (!source || typeof source !== 'object' || Array.isArray(source)) return undefined;
|
|
348
|
+
for (const key of keys) {
|
|
349
|
+
if (hasOwn(source, key) && source[key] !== undefined && source[key] !== null) {
|
|
350
|
+
return source[key];
|
|
351
|
+
}
|
|
352
|
+
}
|
|
353
|
+
return undefined;
|
|
354
|
+
}
|
|
355
|
+
|
|
356
|
+
function trimString(value) {
|
|
357
|
+
return typeof value === 'string' ? value.trim() : '';
|
|
358
|
+
}
|
|
359
|
+
|
|
360
|
+
function stripUndefinedEntries(value) {
|
|
361
|
+
return Object.fromEntries(
|
|
362
|
+
Object.entries(value || {}).filter(([, entry]) => entry !== undefined),
|
|
363
|
+
);
|
|
364
|
+
}
|
|
365
|
+
|
|
366
|
+
function resolvePayloadWorkspaceId(payload, fallbackWorkspaceId) {
|
|
367
|
+
const workspaceId = firstDefined(payload, ['workspace_id', 'workspaceId']);
|
|
368
|
+
if (typeof workspaceId === 'string' && workspaceId.trim().length > 0) {
|
|
369
|
+
return workspaceId.trim();
|
|
370
|
+
}
|
|
371
|
+
return fallbackWorkspaceId || null;
|
|
372
|
+
}
|
|
373
|
+
|
|
374
|
+
function isUuidLike(value) {
|
|
375
|
+
return typeof value === 'string' && /^[0-9a-f]{8}-[0-9a-f-]{27}$/i.test(value.trim());
|
|
376
|
+
}
|
|
377
|
+
|
|
378
|
+
function coercePositiveInteger(value, label) {
|
|
379
|
+
if (value === undefined || value === null || value === '') return undefined;
|
|
380
|
+
const parsed = Number(value);
|
|
381
|
+
if (Number.isInteger(parsed) && parsed > 0) {
|
|
382
|
+
return parsed;
|
|
383
|
+
}
|
|
384
|
+
throw new CliError(`Invalid ${label}: expected a positive integer.`, {
|
|
385
|
+
code: 'INVALID_ARGUMENT',
|
|
386
|
+
exitCode: EXIT_CODES.USAGE,
|
|
387
|
+
hint: isUuidLike(value)
|
|
388
|
+
? `${label} expects a numeric tracking id. Brand-group ids are UUIDs and use brand-group-management instead.`
|
|
389
|
+
: null,
|
|
390
|
+
details: value,
|
|
391
|
+
});
|
|
392
|
+
}
|
|
393
|
+
|
|
394
|
+
function buildPathWithQuery(basePath, query) {
|
|
395
|
+
const params = new URLSearchParams();
|
|
396
|
+
for (const [key, rawValue] of Object.entries(query || {})) {
|
|
397
|
+
if (rawValue === undefined || rawValue === null || rawValue === '') continue;
|
|
398
|
+
if (Array.isArray(rawValue)) {
|
|
399
|
+
for (const entry of rawValue) {
|
|
400
|
+
if (entry !== undefined && entry !== null && entry !== '') {
|
|
401
|
+
params.append(key, String(entry));
|
|
402
|
+
}
|
|
403
|
+
}
|
|
404
|
+
continue;
|
|
405
|
+
}
|
|
406
|
+
params.set(key, String(rawValue));
|
|
407
|
+
}
|
|
408
|
+
const queryString = params.toString();
|
|
409
|
+
return queryString ? `${basePath}?${queryString}` : basePath;
|
|
410
|
+
}
|
|
411
|
+
|
|
412
|
+
function normalizeTrackingType(value) {
|
|
413
|
+
const normalized = trimString(value).toLowerCase();
|
|
414
|
+
if (!normalized) return undefined;
|
|
415
|
+
if (normalized === 'keyword' || normalized === 'search') return 'search';
|
|
416
|
+
if (normalized === 'account' || normalized === 'creator') return 'creator';
|
|
417
|
+
if (normalized === 'hashtag') return 'hashtag';
|
|
418
|
+
throw new CliError(`Invalid tracking type: ${value}`, {
|
|
419
|
+
code: 'INVALID_ARGUMENT',
|
|
420
|
+
exitCode: EXIT_CODES.USAGE,
|
|
421
|
+
hint: 'Use keyword/search, hashtag, or account/creator.',
|
|
422
|
+
});
|
|
423
|
+
}
|
|
424
|
+
|
|
425
|
+
function normalizeTrackingPayload(payload, fallbackWorkspaceId) {
|
|
426
|
+
const trackValue = firstDefined(payload, ['track_value', 'trackValue', 'value']);
|
|
427
|
+
const refreshFrequency = firstDefined(payload, ['refresh_frequency', 'refreshFrequency']);
|
|
428
|
+
const nextRefreshAt = firstDefined(payload, ['next_refresh_at', 'nextRefreshAt']);
|
|
429
|
+
const region = firstDefined(payload, ['region']);
|
|
430
|
+
const platform = firstDefined(payload, ['platform']);
|
|
431
|
+
const brandIds = firstDefined(payload, ['brand_ids', 'brandIds']);
|
|
432
|
+
const includeInactive = firstDefined(payload, ['includeInactive', 'include_inactive']);
|
|
433
|
+
const isActive = firstDefined(payload, ['is_active', 'isActive']);
|
|
434
|
+
const limit = firstDefined(payload, ['limit']);
|
|
435
|
+
const page = firstDefined(payload, ['page']);
|
|
436
|
+
const offset = firstDefined(payload, ['offset']);
|
|
437
|
+
const itemId = firstDefined(payload, ['item_id', 'itemId', 'id']);
|
|
438
|
+
|
|
439
|
+
return stripUndefinedEntries({
|
|
440
|
+
action: trimString(firstDefined(payload, ['action'])) || undefined,
|
|
441
|
+
workspaceId: resolvePayloadWorkspaceId(payload, fallbackWorkspaceId),
|
|
442
|
+
item_id: coercePositiveInteger(itemId, 'item_id'),
|
|
443
|
+
name: trimString(firstDefined(payload, ['name'])) || (trimString(trackValue) || undefined),
|
|
444
|
+
track_type: normalizeTrackingType(firstDefined(payload, ['track_type', 'trackType', 'type'])),
|
|
445
|
+
track_value: trimString(trackValue) || undefined,
|
|
446
|
+
refresh_frequency: trimString(refreshFrequency) || undefined,
|
|
447
|
+
next_refresh_at: nextRefreshAt ?? undefined,
|
|
448
|
+
region: typeof region === 'string' ? region.trim() || undefined : region,
|
|
449
|
+
platform: trimString(platform) || undefined,
|
|
450
|
+
brand_ids: Array.isArray(brandIds) ? brandIds : undefined,
|
|
451
|
+
limit: limit !== undefined ? Number(limit) : undefined,
|
|
452
|
+
page: page !== undefined ? Number(page) : undefined,
|
|
453
|
+
offset: offset !== undefined ? Number(offset) : undefined,
|
|
454
|
+
is_active: typeof isActive === 'boolean' ? isActive : undefined,
|
|
455
|
+
include_inactive: typeof includeInactive === 'boolean' ? includeInactive : undefined,
|
|
456
|
+
});
|
|
457
|
+
}
|
|
458
|
+
|
|
459
|
+
function normalizeGroupManagementPayload(payload, fallbackWorkspaceId) {
|
|
460
|
+
const groupId = firstDefined(payload, ['group_id', 'groupId', 'id']);
|
|
461
|
+
const limit = firstDefined(payload, ['limit']);
|
|
462
|
+
const page = firstDefined(payload, ['page']);
|
|
463
|
+
return stripUndefinedEntries({
|
|
464
|
+
action: trimString(firstDefined(payload, ['action'])) || undefined,
|
|
465
|
+
workspaceId: resolvePayloadWorkspaceId(payload, fallbackWorkspaceId),
|
|
466
|
+
group_id: coercePositiveInteger(groupId, 'group_id'),
|
|
467
|
+
name: trimString(firstDefined(payload, ['name'])) || undefined,
|
|
468
|
+
description: firstDefined(payload, ['description']),
|
|
469
|
+
platform: trimString(firstDefined(payload, ['platform', 'groupPlatform'])) || undefined,
|
|
470
|
+
refresh_frequency: trimString(firstDefined(payload, ['refresh_frequency', 'refreshFrequency'])) || undefined,
|
|
471
|
+
next_refresh_at: firstDefined(payload, ['next_refresh_at', 'nextRefreshAt']) ?? undefined,
|
|
472
|
+
brand_id: trimString(firstDefined(payload, ['brand_id', 'brandId'])) || undefined,
|
|
473
|
+
limit: limit !== undefined ? Number(limit) : undefined,
|
|
474
|
+
page: page !== undefined ? Number(page) : undefined,
|
|
475
|
+
});
|
|
476
|
+
}
|
|
477
|
+
|
|
478
|
+
function normalizeBrandGroupPayload(payload, fallbackWorkspaceId) {
|
|
479
|
+
return stripUndefinedEntries({
|
|
480
|
+
action: trimString(firstDefined(payload, ['action'])) || undefined,
|
|
481
|
+
workspaceId: resolvePayloadWorkspaceId(payload, fallbackWorkspaceId),
|
|
482
|
+
workspace_id: resolvePayloadWorkspaceId(payload, fallbackWorkspaceId) || undefined,
|
|
483
|
+
brand_group_id: trimString(firstDefined(payload, ['brand_group_id', 'brandGroupId', 'group_id', 'groupId', 'id'])) || undefined,
|
|
484
|
+
brand_id: trimString(firstDefined(payload, ['brand_id', 'brandId'])) || undefined,
|
|
485
|
+
name: trimString(firstDefined(payload, ['name'])) || undefined,
|
|
486
|
+
description: firstDefined(payload, ['description']),
|
|
487
|
+
});
|
|
488
|
+
}
|
|
489
|
+
|
|
490
|
+
function normalizeBackfillPayload(payload, fallbackWorkspaceId) {
|
|
491
|
+
return stripUndefinedEntries({
|
|
492
|
+
workspace_id: resolvePayloadWorkspaceId(payload, fallbackWorkspaceId) || undefined,
|
|
493
|
+
brand_id: trimString(firstDefined(payload, ['brand_id', 'brandId'])) || undefined,
|
|
494
|
+
tracking_group_ids: firstDefined(payload, ['tracking_group_ids', 'trackingGroupIds']),
|
|
495
|
+
backfill_days: firstDefined(payload, ['backfill_days', 'backfillDays']),
|
|
496
|
+
max_tracking_groups: firstDefined(payload, ['max_tracking_groups', 'maxTrackingGroups']),
|
|
497
|
+
max_videos: firstDefined(payload, ['max_videos', 'maxVideos']),
|
|
498
|
+
max_summaries: firstDefined(payload, ['max_summaries', 'maxSummaries']),
|
|
499
|
+
bump_user_revision: firstDefined(payload, ['bump_user_revision', 'bumpUserRevision']),
|
|
500
|
+
bump_workspace_revision: firstDefined(payload, ['bump_workspace_revision', 'bumpWorkspaceRevision']),
|
|
501
|
+
});
|
|
502
|
+
}
|
|
503
|
+
|
|
504
|
+
function normalizeTrackingExportPayload(payload, fallbackWorkspaceId) {
|
|
505
|
+
const groupId = firstDefined(payload, ['group_id', 'groupId', 'tracking_group_id', 'trackingGroupId']);
|
|
506
|
+
const itemId = firstDefined(payload, ['tracking_item_id', 'trackingItemId', 'item_id', 'itemId']);
|
|
507
|
+
return stripUndefinedEntries({
|
|
508
|
+
workspace_id: resolvePayloadWorkspaceId(payload, fallbackWorkspaceId) || undefined,
|
|
509
|
+
group_id: coercePositiveInteger(groupId, 'group_id'),
|
|
510
|
+
tracking_item_id: coercePositiveInteger(itemId, 'tracking_item_id'),
|
|
511
|
+
time_period: trimString(firstDefined(payload, ['time_period', 'timePeriod'])) || undefined,
|
|
512
|
+
});
|
|
513
|
+
}
|
|
514
|
+
|
|
515
|
+
function translateTrackingAction(payload, workspaceId) {
|
|
516
|
+
const action = payload.action ? payload.action.toLowerCase() : null;
|
|
517
|
+
if (!action) {
|
|
518
|
+
return {
|
|
519
|
+
method: 'POST',
|
|
520
|
+
pathSuffix: '',
|
|
521
|
+
body: stripUndefinedEntries({
|
|
522
|
+
name: payload.name,
|
|
523
|
+
track_type: payload.track_type,
|
|
524
|
+
track_value: payload.track_value,
|
|
525
|
+
refresh_frequency: payload.refresh_frequency,
|
|
526
|
+
next_refresh_at: payload.next_refresh_at,
|
|
527
|
+
region: payload.region,
|
|
528
|
+
platform: payload.platform,
|
|
529
|
+
brand_ids: payload.brand_ids,
|
|
530
|
+
}),
|
|
531
|
+
workspaceId,
|
|
532
|
+
};
|
|
533
|
+
}
|
|
534
|
+
|
|
535
|
+
if (action === 'list' || action === 'item_list') {
|
|
536
|
+
const limit = Number.isFinite(payload.limit) ? payload.limit : 20;
|
|
537
|
+
const page = Number.isFinite(payload.page) ? Math.max(1, payload.page) : 1;
|
|
538
|
+
const offset = Number.isFinite(payload.offset) ? Math.max(0, payload.offset) : ((page - 1) * limit);
|
|
539
|
+
const isActive = typeof payload.is_active === 'boolean'
|
|
540
|
+
? payload.is_active
|
|
541
|
+
: (payload.include_inactive ? undefined : true);
|
|
542
|
+
return {
|
|
543
|
+
method: 'GET',
|
|
544
|
+
pathSuffix: buildPathWithQuery('', {
|
|
545
|
+
workspace_id: workspaceId || undefined,
|
|
546
|
+
limit,
|
|
547
|
+
offset,
|
|
548
|
+
track_type: payload.track_type,
|
|
549
|
+
track_value: payload.track_value,
|
|
550
|
+
platform: payload.platform,
|
|
551
|
+
region: payload.region,
|
|
552
|
+
is_active: isActive,
|
|
553
|
+
}),
|
|
554
|
+
body: undefined,
|
|
555
|
+
workspaceId,
|
|
556
|
+
};
|
|
557
|
+
}
|
|
558
|
+
|
|
559
|
+
if (action === 'get' || action === 'item_get') {
|
|
560
|
+
const itemId = coercePositiveInteger(payload.item_id, 'item_id');
|
|
561
|
+
if (!itemId) {
|
|
562
|
+
throw new CliError('item_id is required for tracking get.', {
|
|
563
|
+
code: 'MISSING_ARGUMENT',
|
|
564
|
+
exitCode: EXIT_CODES.USAGE,
|
|
565
|
+
});
|
|
566
|
+
}
|
|
567
|
+
return {
|
|
568
|
+
method: 'GET',
|
|
569
|
+
pathSuffix: buildPathWithQuery(`/${itemId}`, { workspace_id: workspaceId || undefined }),
|
|
570
|
+
body: undefined,
|
|
571
|
+
workspaceId,
|
|
572
|
+
};
|
|
573
|
+
}
|
|
574
|
+
|
|
575
|
+
if (action === 'create' || action === 'item_create') {
|
|
576
|
+
return {
|
|
577
|
+
method: 'POST',
|
|
578
|
+
pathSuffix: '',
|
|
579
|
+
body: stripUndefinedEntries({
|
|
580
|
+
name: payload.name,
|
|
581
|
+
track_type: payload.track_type,
|
|
582
|
+
track_value: payload.track_value,
|
|
583
|
+
refresh_frequency: payload.refresh_frequency,
|
|
584
|
+
next_refresh_at: payload.next_refresh_at,
|
|
585
|
+
region: payload.region,
|
|
586
|
+
platform: payload.platform,
|
|
587
|
+
brand_ids: payload.brand_ids,
|
|
588
|
+
}),
|
|
589
|
+
workspaceId,
|
|
590
|
+
};
|
|
591
|
+
}
|
|
592
|
+
|
|
593
|
+
if (action === 'update' || action === 'item_update') {
|
|
594
|
+
const itemId = coercePositiveInteger(payload.item_id, 'item_id');
|
|
595
|
+
if (!itemId) {
|
|
596
|
+
throw new CliError('item_id is required for tracking update.', {
|
|
597
|
+
code: 'MISSING_ARGUMENT',
|
|
598
|
+
exitCode: EXIT_CODES.USAGE,
|
|
599
|
+
});
|
|
600
|
+
}
|
|
601
|
+
return {
|
|
602
|
+
method: 'PATCH',
|
|
603
|
+
pathSuffix: buildPathWithQuery(`/${itemId}`, { workspace_id: workspaceId || undefined }),
|
|
604
|
+
body: stripUndefinedEntries({
|
|
605
|
+
refresh_frequency: payload.refresh_frequency,
|
|
606
|
+
next_refresh_at: payload.next_refresh_at,
|
|
607
|
+
}),
|
|
608
|
+
workspaceId,
|
|
609
|
+
};
|
|
610
|
+
}
|
|
611
|
+
|
|
612
|
+
if (action === 'delete' || action === 'item_delete') {
|
|
613
|
+
const itemId = coercePositiveInteger(payload.item_id, 'item_id');
|
|
614
|
+
if (!itemId) {
|
|
615
|
+
throw new CliError('item_id is required for tracking delete.', {
|
|
616
|
+
code: 'MISSING_ARGUMENT',
|
|
617
|
+
exitCode: EXIT_CODES.USAGE,
|
|
618
|
+
});
|
|
619
|
+
}
|
|
620
|
+
return {
|
|
621
|
+
method: 'DELETE',
|
|
622
|
+
pathSuffix: buildPathWithQuery(`/${itemId}`, { workspace_id: workspaceId || undefined }),
|
|
623
|
+
body: undefined,
|
|
624
|
+
workspaceId,
|
|
625
|
+
};
|
|
626
|
+
}
|
|
627
|
+
|
|
628
|
+
if (action === 'refresh' || action === 'item_refresh') {
|
|
629
|
+
const itemId = coercePositiveInteger(payload.item_id, 'item_id');
|
|
630
|
+
if (!itemId) {
|
|
631
|
+
throw new CliError('item_id is required for tracking refresh.', {
|
|
632
|
+
code: 'MISSING_ARGUMENT',
|
|
633
|
+
exitCode: EXIT_CODES.USAGE,
|
|
634
|
+
});
|
|
635
|
+
}
|
|
636
|
+
return {
|
|
637
|
+
method: 'POST',
|
|
638
|
+
pathSuffix: buildPathWithQuery(`/${itemId}/refresh`, { workspace_id: workspaceId || undefined }),
|
|
639
|
+
body: {},
|
|
640
|
+
workspaceId,
|
|
641
|
+
};
|
|
642
|
+
}
|
|
643
|
+
|
|
644
|
+
throw new CliError(`Unsupported tracking action: ${payload.action}`, {
|
|
645
|
+
code: 'INVALID_ARGUMENT',
|
|
646
|
+
exitCode: EXIT_CODES.USAGE,
|
|
647
|
+
hint: 'Supported tracking actions: list, get, create, update, delete, refresh.',
|
|
648
|
+
});
|
|
649
|
+
}
|
|
650
|
+
|
|
651
|
+
function translateGroupManagementAction(payload, workspaceId, originalMethod) {
|
|
652
|
+
const action = payload.action ? payload.action.toLowerCase() : null;
|
|
653
|
+
|
|
654
|
+
if (!action && originalMethod === 'GET') {
|
|
655
|
+
return {
|
|
656
|
+
method: 'GET',
|
|
657
|
+
pathSuffix: buildPathWithQuery('/groups', { workspace_id: workspaceId || undefined }),
|
|
658
|
+
body: undefined,
|
|
659
|
+
workspaceId,
|
|
660
|
+
};
|
|
661
|
+
}
|
|
662
|
+
|
|
663
|
+
if (!action) {
|
|
664
|
+
return {
|
|
665
|
+
method: 'POST',
|
|
666
|
+
pathSuffix: buildPathWithQuery('/groups', { workspace_id: workspaceId || undefined }),
|
|
667
|
+
body: stripUndefinedEntries({
|
|
668
|
+
name: payload.name,
|
|
669
|
+
description: payload.description,
|
|
670
|
+
platform: payload.platform,
|
|
671
|
+
refresh_frequency: payload.refresh_frequency,
|
|
672
|
+
next_refresh_at: payload.next_refresh_at,
|
|
673
|
+
brand_id: payload.brand_id,
|
|
674
|
+
}),
|
|
675
|
+
workspaceId,
|
|
676
|
+
};
|
|
677
|
+
}
|
|
678
|
+
|
|
679
|
+
if (action === 'list' || action === 'group_list') {
|
|
680
|
+
return {
|
|
681
|
+
method: 'GET',
|
|
682
|
+
pathSuffix: buildPathWithQuery('/groups', { workspace_id: workspaceId || undefined }),
|
|
683
|
+
body: undefined,
|
|
684
|
+
workspaceId,
|
|
685
|
+
};
|
|
686
|
+
}
|
|
687
|
+
|
|
688
|
+
if (action === 'get' || action === 'group_get') {
|
|
689
|
+
const groupId = coercePositiveInteger(payload.group_id, 'group_id');
|
|
690
|
+
if (!groupId) {
|
|
691
|
+
throw new CliError('group_id is required for group get.', {
|
|
692
|
+
code: 'MISSING_ARGUMENT',
|
|
693
|
+
exitCode: EXIT_CODES.USAGE,
|
|
694
|
+
});
|
|
695
|
+
}
|
|
696
|
+
return {
|
|
697
|
+
method: 'GET',
|
|
698
|
+
pathSuffix: buildPathWithQuery(`/groups/${groupId}`, { workspace_id: workspaceId || undefined }),
|
|
699
|
+
body: undefined,
|
|
700
|
+
workspaceId,
|
|
701
|
+
};
|
|
702
|
+
}
|
|
703
|
+
|
|
704
|
+
if (action === 'create' || action === 'group_create') {
|
|
705
|
+
return {
|
|
706
|
+
method: 'POST',
|
|
707
|
+
pathSuffix: buildPathWithQuery('/groups', { workspace_id: workspaceId || undefined }),
|
|
708
|
+
body: stripUndefinedEntries({
|
|
709
|
+
name: payload.name,
|
|
710
|
+
description: payload.description,
|
|
711
|
+
platform: payload.platform,
|
|
712
|
+
refresh_frequency: payload.refresh_frequency,
|
|
713
|
+
next_refresh_at: payload.next_refresh_at,
|
|
714
|
+
brand_id: payload.brand_id,
|
|
715
|
+
}),
|
|
716
|
+
workspaceId,
|
|
717
|
+
};
|
|
718
|
+
}
|
|
719
|
+
|
|
720
|
+
if (action === 'update' || action === 'group_update') {
|
|
721
|
+
const groupId = coercePositiveInteger(payload.group_id, 'group_id');
|
|
722
|
+
if (!groupId) {
|
|
723
|
+
throw new CliError('group_id is required for group update.', {
|
|
724
|
+
code: 'MISSING_ARGUMENT',
|
|
725
|
+
exitCode: EXIT_CODES.USAGE,
|
|
726
|
+
});
|
|
727
|
+
}
|
|
728
|
+
return {
|
|
729
|
+
method: 'PATCH',
|
|
730
|
+
pathSuffix: buildPathWithQuery(`/groups/${groupId}`, { workspace_id: workspaceId || undefined }),
|
|
731
|
+
body: stripUndefinedEntries({
|
|
732
|
+
name: payload.name,
|
|
733
|
+
description: payload.description,
|
|
734
|
+
refresh_frequency: payload.refresh_frequency,
|
|
735
|
+
next_refresh_at: payload.next_refresh_at,
|
|
736
|
+
brand_id: payload.brand_id,
|
|
737
|
+
}),
|
|
738
|
+
workspaceId,
|
|
739
|
+
};
|
|
740
|
+
}
|
|
741
|
+
|
|
742
|
+
if (action === 'delete' || action === 'group_delete') {
|
|
743
|
+
const groupId = coercePositiveInteger(payload.group_id, 'group_id');
|
|
744
|
+
if (!groupId) {
|
|
745
|
+
throw new CliError('group_id is required for group delete.', {
|
|
746
|
+
code: 'MISSING_ARGUMENT',
|
|
747
|
+
exitCode: EXIT_CODES.USAGE,
|
|
748
|
+
});
|
|
749
|
+
}
|
|
750
|
+
return {
|
|
751
|
+
method: 'DELETE',
|
|
752
|
+
pathSuffix: buildPathWithQuery(`/groups/${groupId}`, { workspace_id: workspaceId || undefined }),
|
|
753
|
+
body: undefined,
|
|
754
|
+
workspaceId,
|
|
755
|
+
};
|
|
756
|
+
}
|
|
757
|
+
|
|
758
|
+
if (action === 'refresh' || action === 'group_refresh') {
|
|
759
|
+
const groupId = coercePositiveInteger(payload.group_id, 'group_id');
|
|
760
|
+
if (!groupId) {
|
|
761
|
+
throw new CliError('group_id is required for group refresh.', {
|
|
762
|
+
code: 'MISSING_ARGUMENT',
|
|
763
|
+
exitCode: EXIT_CODES.USAGE,
|
|
764
|
+
});
|
|
765
|
+
}
|
|
766
|
+
return {
|
|
767
|
+
method: 'POST',
|
|
768
|
+
pathSuffix: buildPathWithQuery(`/groups/${groupId}/refresh`, { workspace_id: workspaceId || undefined }),
|
|
769
|
+
body: {},
|
|
770
|
+
workspaceId,
|
|
771
|
+
};
|
|
772
|
+
}
|
|
773
|
+
|
|
774
|
+
if (action === 'list_items' || action === 'group_list_items') {
|
|
775
|
+
const groupId = coercePositiveInteger(payload.group_id, 'group_id');
|
|
776
|
+
if (!groupId) {
|
|
777
|
+
throw new CliError('group_id is required for group list_items.', {
|
|
778
|
+
code: 'MISSING_ARGUMENT',
|
|
779
|
+
exitCode: EXIT_CODES.USAGE,
|
|
780
|
+
});
|
|
781
|
+
}
|
|
782
|
+
return {
|
|
783
|
+
method: 'GET',
|
|
784
|
+
pathSuffix: buildPathWithQuery(`/groups/${groupId}/items`, {
|
|
785
|
+
workspace_id: workspaceId || undefined,
|
|
786
|
+
page: Number.isFinite(payload.page) ? payload.page : undefined,
|
|
787
|
+
limit: Number.isFinite(payload.limit) ? payload.limit : undefined,
|
|
788
|
+
}),
|
|
789
|
+
body: undefined,
|
|
790
|
+
workspaceId,
|
|
791
|
+
};
|
|
792
|
+
}
|
|
793
|
+
|
|
794
|
+
throw new CliError(`Unsupported group-management action: ${payload.action}`, {
|
|
795
|
+
code: 'INVALID_ARGUMENT',
|
|
796
|
+
exitCode: EXIT_CODES.USAGE,
|
|
797
|
+
hint: 'Supported group-management actions: list, get, create, update, delete, refresh, list_items.',
|
|
798
|
+
});
|
|
799
|
+
}
|
|
800
|
+
|
|
801
|
+
function translateBrandGroupAction(payload, workspaceId) {
|
|
802
|
+
const action = payload.action ? payload.action.toLowerCase() : null;
|
|
803
|
+
const brandGroupId = payload.brand_group_id || undefined;
|
|
804
|
+
const effectiveWorkspaceId = payload.workspace_id || workspaceId || undefined;
|
|
805
|
+
|
|
806
|
+
if (!action) {
|
|
807
|
+
return {
|
|
808
|
+
method: 'POST',
|
|
809
|
+
pathSuffix: '',
|
|
810
|
+
body: stripUndefinedEntries({
|
|
811
|
+
name: payload.name,
|
|
812
|
+
description: payload.description,
|
|
813
|
+
workspace_id: effectiveWorkspaceId,
|
|
814
|
+
}),
|
|
815
|
+
workspaceId: workspaceId || null,
|
|
816
|
+
};
|
|
817
|
+
}
|
|
818
|
+
|
|
819
|
+
if (action === 'list') {
|
|
820
|
+
return {
|
|
821
|
+
method: 'GET',
|
|
822
|
+
pathSuffix: buildPathWithQuery('', { workspace_id: effectiveWorkspaceId }),
|
|
823
|
+
body: undefined,
|
|
824
|
+
workspaceId: workspaceId || null,
|
|
825
|
+
};
|
|
826
|
+
}
|
|
827
|
+
|
|
828
|
+
if (action === 'create') {
|
|
829
|
+
return {
|
|
830
|
+
method: 'POST',
|
|
831
|
+
pathSuffix: '',
|
|
832
|
+
body: stripUndefinedEntries({
|
|
833
|
+
name: payload.name,
|
|
834
|
+
description: payload.description,
|
|
835
|
+
workspace_id: effectiveWorkspaceId,
|
|
836
|
+
}),
|
|
837
|
+
workspaceId: workspaceId || null,
|
|
838
|
+
};
|
|
839
|
+
}
|
|
840
|
+
|
|
841
|
+
if (action === 'update') {
|
|
842
|
+
if (!brandGroupId) {
|
|
843
|
+
throw new CliError('brand_group_id is required for brand-group update.', {
|
|
844
|
+
code: 'MISSING_ARGUMENT',
|
|
845
|
+
exitCode: EXIT_CODES.USAGE,
|
|
846
|
+
});
|
|
847
|
+
}
|
|
848
|
+
return {
|
|
849
|
+
method: 'PATCH',
|
|
850
|
+
pathSuffix: `/${brandGroupId}`,
|
|
851
|
+
body: stripUndefinedEntries({
|
|
852
|
+
name: payload.name,
|
|
853
|
+
description: payload.description,
|
|
854
|
+
}),
|
|
855
|
+
workspaceId: workspaceId || null,
|
|
856
|
+
};
|
|
857
|
+
}
|
|
858
|
+
|
|
859
|
+
if (action === 'delete') {
|
|
860
|
+
if (!brandGroupId) {
|
|
861
|
+
throw new CliError('brand_group_id is required for brand-group delete.', {
|
|
862
|
+
code: 'MISSING_ARGUMENT',
|
|
863
|
+
exitCode: EXIT_CODES.USAGE,
|
|
864
|
+
});
|
|
865
|
+
}
|
|
866
|
+
return {
|
|
867
|
+
method: 'DELETE',
|
|
868
|
+
pathSuffix: `/${brandGroupId}`,
|
|
869
|
+
body: undefined,
|
|
870
|
+
workspaceId: workspaceId || null,
|
|
871
|
+
};
|
|
872
|
+
}
|
|
873
|
+
|
|
874
|
+
if (action === 'add_member') {
|
|
875
|
+
if (!brandGroupId || !payload.brand_id) {
|
|
876
|
+
throw new CliError('brand_group_id and brand_id are required for brand-group add_member.', {
|
|
877
|
+
code: 'MISSING_ARGUMENT',
|
|
878
|
+
exitCode: EXIT_CODES.USAGE,
|
|
879
|
+
});
|
|
880
|
+
}
|
|
881
|
+
return {
|
|
882
|
+
method: 'POST',
|
|
883
|
+
pathSuffix: `/${brandGroupId}/members`,
|
|
884
|
+
body: { brand_id: payload.brand_id },
|
|
885
|
+
workspaceId: workspaceId || null,
|
|
886
|
+
};
|
|
887
|
+
}
|
|
888
|
+
|
|
889
|
+
if (action === 'remove_member') {
|
|
890
|
+
if (!brandGroupId || !payload.brand_id) {
|
|
891
|
+
throw new CliError('brand_group_id and brand_id are required for brand-group remove_member.', {
|
|
892
|
+
code: 'MISSING_ARGUMENT',
|
|
893
|
+
exitCode: EXIT_CODES.USAGE,
|
|
894
|
+
});
|
|
895
|
+
}
|
|
896
|
+
return {
|
|
897
|
+
method: 'DELETE',
|
|
898
|
+
pathSuffix: `/${brandGroupId}/members/${payload.brand_id}`,
|
|
899
|
+
body: undefined,
|
|
900
|
+
workspaceId: workspaceId || null,
|
|
901
|
+
};
|
|
902
|
+
}
|
|
903
|
+
|
|
904
|
+
throw new CliError(`Unsupported brand-group-management action: ${payload.action}`, {
|
|
905
|
+
code: 'INVALID_ARGUMENT',
|
|
906
|
+
exitCode: EXIT_CODES.USAGE,
|
|
907
|
+
hint: 'Supported brand-group-management actions: list, create, update, delete, add_member, remove_member.',
|
|
908
|
+
});
|
|
909
|
+
}
|
|
910
|
+
|
|
911
|
+
function translateToolInvocation({ functionName, method, payload, resolvedWorkspaceId }) {
|
|
912
|
+
if (!isJsonObject(payload)) {
|
|
913
|
+
return {
|
|
914
|
+
method,
|
|
915
|
+
pathSuffix: '',
|
|
916
|
+
body: payload,
|
|
917
|
+
workspaceId: resolvedWorkspaceId,
|
|
918
|
+
normalizedPayload: payload,
|
|
919
|
+
};
|
|
920
|
+
}
|
|
921
|
+
|
|
922
|
+
if (functionName === 'tracking') {
|
|
923
|
+
const normalizedPayload = normalizeTrackingPayload(payload, resolvedWorkspaceId);
|
|
924
|
+
const workspaceId = normalizedPayload.workspaceId || resolvedWorkspaceId || null;
|
|
925
|
+
const translated = translateTrackingAction(normalizedPayload, workspaceId);
|
|
926
|
+
return { ...translated, normalizedPayload };
|
|
927
|
+
}
|
|
928
|
+
|
|
929
|
+
if (functionName === 'group-management') {
|
|
930
|
+
const normalizedPayload = normalizeGroupManagementPayload(payload, resolvedWorkspaceId);
|
|
931
|
+
const workspaceId = normalizedPayload.workspaceId || resolvedWorkspaceId || null;
|
|
932
|
+
const translated = translateGroupManagementAction(normalizedPayload, workspaceId, method);
|
|
933
|
+
return { ...translated, normalizedPayload };
|
|
934
|
+
}
|
|
935
|
+
|
|
936
|
+
if (functionName === 'brand-group-management') {
|
|
937
|
+
const normalizedPayload = normalizeBrandGroupPayload(payload, resolvedWorkspaceId);
|
|
938
|
+
const workspaceId = normalizedPayload.workspaceId || resolvedWorkspaceId || null;
|
|
939
|
+
const translated = translateBrandGroupAction(normalizedPayload, workspaceId);
|
|
940
|
+
return { ...translated, normalizedPayload };
|
|
941
|
+
}
|
|
942
|
+
|
|
943
|
+
if (functionName === 'enqueue-brand-metrics-backfill') {
|
|
944
|
+
const normalizedPayload = normalizeBackfillPayload(payload, resolvedWorkspaceId);
|
|
945
|
+
if (!normalizedPayload.brand_id && hasOwn(payload, 'group_id')) {
|
|
946
|
+
throw new CliError('enqueue-brand-metrics-backfill expects brand_id, not group_id.', {
|
|
947
|
+
code: 'INVALID_ARGUMENT',
|
|
948
|
+
exitCode: EXIT_CODES.USAGE,
|
|
949
|
+
hint: 'Use group-management refresh for tracking groups. Backfill jobs refresh brand metrics for a workspace brand.',
|
|
950
|
+
});
|
|
951
|
+
}
|
|
952
|
+
return {
|
|
953
|
+
method,
|
|
954
|
+
pathSuffix: '',
|
|
955
|
+
body: normalizedPayload,
|
|
956
|
+
workspaceId: resolvedWorkspaceId,
|
|
957
|
+
normalizedPayload,
|
|
958
|
+
};
|
|
959
|
+
}
|
|
960
|
+
|
|
961
|
+
if (functionName === 'export_tracking_data') {
|
|
962
|
+
const normalizedPayload = normalizeTrackingExportPayload(payload, resolvedWorkspaceId);
|
|
963
|
+
return {
|
|
964
|
+
method,
|
|
965
|
+
pathSuffix: '',
|
|
966
|
+
body: normalizedPayload,
|
|
967
|
+
workspaceId: normalizedPayload.workspace_id || resolvedWorkspaceId || null,
|
|
968
|
+
normalizedPayload,
|
|
969
|
+
};
|
|
970
|
+
}
|
|
971
|
+
|
|
972
|
+
return {
|
|
973
|
+
method,
|
|
974
|
+
pathSuffix: '',
|
|
975
|
+
body: payload,
|
|
976
|
+
workspaceId: resolvedWorkspaceId,
|
|
977
|
+
normalizedPayload: payload,
|
|
978
|
+
};
|
|
979
|
+
}
|
|
980
|
+
|
|
293
981
|
function isJsonObject(value) {
|
|
294
982
|
return Boolean(value) && typeof value === 'object' && !Array.isArray(value);
|
|
295
983
|
}
|
|
296
984
|
|
|
985
|
+
function isStateChangingMethod(method) {
|
|
986
|
+
return !['GET', 'HEAD', 'OPTIONS'].includes(method);
|
|
987
|
+
}
|
|
988
|
+
|
|
989
|
+
function emitWorkspaceContext(opts, { workspaceId, source, functionName, method }) {
|
|
990
|
+
if (!workspaceId || !isStateChangingMethod(method)) return;
|
|
991
|
+
process.stderr.write(
|
|
992
|
+
`[socialseal] Workspace: ${workspaceId}${source ? ` (${source})` : ''} for ${functionName} ${method}\n`,
|
|
993
|
+
);
|
|
994
|
+
}
|
|
995
|
+
|
|
297
996
|
function sleep(ms) {
|
|
298
997
|
return new Promise((resolve) => setTimeout(resolve, ms));
|
|
299
998
|
}
|
|
@@ -431,6 +1130,10 @@ function mapStatusToExitCode(status) {
|
|
|
431
1130
|
return EXIT_CODES.UNKNOWN;
|
|
432
1131
|
}
|
|
433
1132
|
|
|
1133
|
+
function isLocallyDisabledByDefaultFunction(functionName) {
|
|
1134
|
+
return functionName === 'group-management' || functionName === 'export_tracking_data';
|
|
1135
|
+
}
|
|
1136
|
+
|
|
434
1137
|
function buildStatusHint(status, context = {}) {
|
|
435
1138
|
switch (status) {
|
|
436
1139
|
case 401:
|
|
@@ -438,13 +1141,16 @@ function buildStatusHint(status, context = {}) {
|
|
|
438
1141
|
return 'Check your CLI key and workspace access.';
|
|
439
1142
|
case 404:
|
|
440
1143
|
if (context.functionName) {
|
|
1144
|
+
if (isLocallyDisabledByDefaultFunction(context.functionName)) {
|
|
1145
|
+
return `Unknown function "${context.functionName}". This tool is listed in the static registry, but it is disabled by default in some local Supabase environments. Check the deployment or enable it in supabase/config.toml.`;
|
|
1146
|
+
}
|
|
441
1147
|
return `Unknown function "${context.functionName}". Double-check the name and API base.`;
|
|
442
1148
|
}
|
|
443
1149
|
return 'Check the API base URL and endpoint path.';
|
|
444
1150
|
case 405:
|
|
445
1151
|
return `Method not allowed. Try --method GET or ensure the endpoint supports ${context.method || 'this method'}.`;
|
|
446
1152
|
case 422:
|
|
447
|
-
return 'Validation error. Review the JSON payload schema.';
|
|
1153
|
+
return 'Validation error. Review the JSON payload schema. For tracking/group tools, prefer the CLI action aliases or the documented REST semantics.';
|
|
448
1154
|
default:
|
|
449
1155
|
return null;
|
|
450
1156
|
}
|
|
@@ -991,19 +1697,38 @@ async function handleToolsCall(opts) {
|
|
|
991
1697
|
const supabaseUrl = resolveLegacyUrl(resolveSupabaseUrl(opts, config), 'SOCIALSEAL_SUPABASE_URL');
|
|
992
1698
|
const { resolvedApiBase, legacyUrl, useGateway } = resolveApiTarget({ apiBase, legacyUrl: supabaseUrl });
|
|
993
1699
|
const timeoutMs = resolveTimeoutMs(opts, config);
|
|
994
|
-
const { workspaceId: resolvedWorkspaceId } = resolveWorkspaceSelection(opts, config);
|
|
1700
|
+
const { workspaceId: resolvedWorkspaceId, source: workspaceSource } = resolveWorkspaceSelection(opts, config);
|
|
995
1701
|
|
|
996
1702
|
const parsedPayload = parseJsonInput(opts.body, { label: 'body' }) ?? {};
|
|
997
1703
|
const mergedPayload = mergeWorkspaceIdIntoPayload(parsedPayload, resolvedWorkspaceId);
|
|
998
|
-
const
|
|
999
|
-
const payload = applySearchJourneyRunAsyncStart(mergedPayload, { ...opts, method });
|
|
1704
|
+
const requestedMethod = normalizeMethod(opts.method);
|
|
1705
|
+
const payload = applySearchJourneyRunAsyncStart(mergedPayload, { ...opts, method: requestedMethod });
|
|
1706
|
+
const translated = translateToolInvocation({
|
|
1707
|
+
functionName: opts.function,
|
|
1708
|
+
method: requestedMethod,
|
|
1709
|
+
payload,
|
|
1710
|
+
resolvedWorkspaceId,
|
|
1711
|
+
});
|
|
1712
|
+
const method = normalizeMethod(translated.method);
|
|
1713
|
+
const effectiveWorkspaceId = translated.workspaceId ?? resolvedWorkspaceId ?? null;
|
|
1714
|
+
const path = useGateway
|
|
1715
|
+
? `/cli/tools/${opts.function}${translated.pathSuffix || ''}`
|
|
1716
|
+
: `/functions/v1/${opts.function}${translated.pathSuffix || ''}`;
|
|
1717
|
+
|
|
1718
|
+
emitWorkspaceContext(opts, {
|
|
1719
|
+
workspaceId: effectiveWorkspaceId,
|
|
1720
|
+
source: effectiveWorkspaceId === resolvedWorkspaceId ? workspaceSource : 'body',
|
|
1721
|
+
functionName: opts.function,
|
|
1722
|
+
method,
|
|
1723
|
+
});
|
|
1724
|
+
|
|
1000
1725
|
const res = await callApi({
|
|
1001
1726
|
apiBase: useGateway ? resolvedApiBase : legacyUrl,
|
|
1002
1727
|
apiKey,
|
|
1003
|
-
path
|
|
1728
|
+
path,
|
|
1004
1729
|
method,
|
|
1005
|
-
body:
|
|
1006
|
-
workspaceId:
|
|
1730
|
+
body: translated.body,
|
|
1731
|
+
workspaceId: effectiveWorkspaceId,
|
|
1007
1732
|
timeoutMs,
|
|
1008
1733
|
});
|
|
1009
1734
|
|
|
@@ -1068,7 +1793,7 @@ function handleToolsList(opts) {
|
|
|
1068
1793
|
const payload = {
|
|
1069
1794
|
discovery: 'built_in_registry',
|
|
1070
1795
|
tools: KNOWN_TOOLS,
|
|
1071
|
-
note:
|
|
1796
|
+
note: STATIC_TOOL_REGISTRY_NOTE,
|
|
1072
1797
|
};
|
|
1073
1798
|
|
|
1074
1799
|
if (opts.json) {
|
|
@@ -1085,7 +1810,16 @@ function handleToolsList(opts) {
|
|
|
1085
1810
|
currentCategory = tool.category;
|
|
1086
1811
|
process.stdout.write(`\n${currentCategory}\n`);
|
|
1087
1812
|
}
|
|
1088
|
-
|
|
1813
|
+
const qualifiers = [
|
|
1814
|
+
tool.objectType ? `object=${tool.objectType}` : null,
|
|
1815
|
+
tool.transport ? `transport=${tool.transport}` : null,
|
|
1816
|
+
tool.knownLocalDevState ? `local=${tool.knownLocalDevState}` : null,
|
|
1817
|
+
].filter(Boolean);
|
|
1818
|
+
const qualifierText = qualifiers.length > 0 ? ` [${qualifiers.join(', ')}]` : '';
|
|
1819
|
+
process.stdout.write(`- ${tool.name}${qualifierText}: ${tool.description}\n`);
|
|
1820
|
+
if (tool.notes) {
|
|
1821
|
+
process.stdout.write(` note: ${tool.notes}\n`);
|
|
1822
|
+
}
|
|
1089
1823
|
}
|
|
1090
1824
|
|
|
1091
1825
|
process.stdout.write('\n[socialseal] Call a tool with: socialseal tools call --function <name> --body @payload.json\n');
|
|
@@ -1107,6 +1841,13 @@ async function handleDataExportTracking(opts) {
|
|
|
1107
1841
|
});
|
|
1108
1842
|
}
|
|
1109
1843
|
|
|
1844
|
+
if (opts.groupId !== undefined) {
|
|
1845
|
+
opts.groupId = coercePositiveInteger(opts.groupId, 'group_id');
|
|
1846
|
+
}
|
|
1847
|
+
if (opts.itemId !== undefined) {
|
|
1848
|
+
opts.itemId = coercePositiveInteger(opts.itemId, 'tracking_item_id');
|
|
1849
|
+
}
|
|
1850
|
+
|
|
1110
1851
|
const payload = {
|
|
1111
1852
|
tracking_item_id: opts.itemId || undefined,
|
|
1112
1853
|
group_id: opts.groupId || undefined,
|