@desplega.ai/agent-swarm 1.87.0 → 1.89.0
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/README.md +5 -1
- package/openapi.json +53 -1
- package/package.json +6 -5
- package/plugin/skills/composio/SKILL.md +98 -0
- package/src/be/db.ts +374 -9
- package/src/be/migrations/080_skill_system_defaults.sql +8 -0
- package/src/be/migrations/081_metrics.sql +39 -0
- package/src/be/migrations/082_user_audit_fields.sql +120 -0
- package/src/be/modelsdev-cache.json +3825 -2417
- package/src/be/seed/registry.ts +3 -2
- package/src/be/seed-skills/index.ts +179 -0
- package/src/cli.tsx +51 -4
- package/src/commands/e2b-stack-wizard.tsx +394 -0
- package/src/commands/e2b.ts +1352 -53
- package/src/commands/onboard/dashboard-url.ts +29 -0
- package/src/commands/onboard/steps/post-dashboard.tsx +3 -1
- package/src/commands/onboard.tsx +3 -1
- package/src/commands/runner.ts +154 -22
- package/src/commands/x.ts +118 -0
- package/src/e2b/dispatch.ts +234 -18
- package/src/github/handlers.ts +40 -1
- package/src/heartbeat/heartbeat.ts +26 -5
- package/src/http/active-sessions.ts +32 -1
- package/src/http/auth.ts +36 -0
- package/src/http/core.ts +20 -16
- package/src/http/db-query.ts +20 -0
- package/src/http/index.ts +2 -0
- package/src/http/memory.ts +13 -1
- package/src/http/metrics.ts +447 -0
- package/src/http/operator-actor.ts +9 -0
- package/src/http/poll.ts +11 -1
- package/src/http/skills.ts +53 -0
- package/src/http/tasks.ts +4 -1
- package/src/http/webhooks.ts +75 -0
- package/src/http/workflows.ts +5 -1
- package/src/integrations/kapso/client.ts +82 -0
- package/src/memory/automatic-task-gate.ts +47 -0
- package/src/metrics/version.ts +26 -0
- package/src/prompts/base-prompt.ts +24 -1
- package/src/prompts/session-templates.ts +74 -0
- package/src/providers/claude-adapter.ts +19 -0
- package/src/providers/codex-adapter.ts +22 -0
- package/src/providers/ctx-mode-env.ts +10 -0
- package/src/providers/opencode-adapter.ts +72 -7
- package/src/server.ts +10 -1
- package/src/slack/blocks.ts +12 -4
- package/src/slack/watcher.ts +3 -3
- package/src/telemetry.ts +14 -1
- package/src/templates.d.ts +4 -0
- package/src/tests/base-prompt.test.ts +76 -0
- package/src/tests/budget-claim-gate.test.ts +26 -0
- package/src/tests/claude-adapter.test.ts +86 -1
- package/src/tests/codex-adapter.test.ts +89 -0
- package/src/tests/core-auth.test.ts +8 -1
- package/src/tests/e2b-dispatch.test.ts +603 -11
- package/src/tests/events-http.test.ts +6 -2
- package/src/tests/github-handlers-cancel-config.test.ts +262 -0
- package/src/tests/heartbeat.test.ts +84 -3
- package/src/tests/http-api-integration.test.ts +116 -1
- package/src/tests/kapso-client.test.ts +74 -1
- package/src/tests/kapso-inbound.test.ts +60 -2
- package/src/tests/metrics-http.test.ts +247 -0
- package/src/tests/opencode-adapter.test.ts +185 -30
- package/src/tests/prompt-template-session.test.ts +4 -2
- package/src/tests/runner-repo-autostash.test.ts +117 -0
- package/src/tests/runner-requester-profile.test.ts +25 -0
- package/src/tests/runner-skills-refresh.test.ts +1 -1
- package/src/tests/self-improvement.test.ts +89 -0
- package/src/tests/skill-update-scope.test.ts +88 -1
- package/src/tests/slack-blocks.test.ts +15 -0
- package/src/tests/swarm-x-tool.test.ts +90 -0
- package/src/tests/system-default-skills.test.ts +122 -0
- package/src/tests/telemetry-init.test.ts +86 -0
- package/src/tests/ui-logs-parser.test.ts +271 -0
- package/src/tests/user-token-rest-auth.test.ts +129 -0
- package/src/tests/workflow-async-v2.test.ts +23 -0
- package/src/tests/x-composio.test.ts +122 -0
- package/src/tools/create-metric.ts +191 -0
- package/src/tools/skills/skill-delete.ts +14 -0
- package/src/tools/skills/skill-update.ts +14 -0
- package/src/tools/store-progress.ts +19 -5
- package/src/tools/swarm-x.ts +116 -0
- package/src/tools/tool-config.ts +6 -0
- package/src/types.ts +121 -0
- package/src/utils/request-auth-context.ts +28 -0
- package/src/utils/skills-refresh.ts +2 -2
- package/src/workflows/engine.ts +24 -2
- package/src/workflows/executors/agent-task.ts +2 -0
- package/src/x/composio.ts +295 -0
- package/templates/skills/artifacts/config.json +1 -0
- package/templates/skills/attio-interaction/SKILL.md +279 -0
- package/templates/skills/attio-interaction/config.json +14 -0
- package/templates/skills/attio-interaction/content.md +272 -0
- package/templates/skills/kv-storage/config.json +1 -0
- package/templates/skills/pages/config.json +1 -0
- package/templates/skills/scheduled-task-resilience/config.json +1 -0
- package/templates/skills/swarm-scripts/SKILL.md +91 -0
- package/templates/skills/swarm-scripts/config.json +14 -0
- package/templates/skills/swarm-scripts/content.md +86 -0
- package/templates/skills/workflow-iterate/config.json +1 -0
- package/templates/skills/workflow-structured-output/config.json +1 -0
- package/tsconfig.json +2 -1
package/src/be/db.ts
CHANGED
|
@@ -42,6 +42,11 @@ import type {
|
|
|
42
42
|
McpServerScope,
|
|
43
43
|
McpServerTransport,
|
|
44
44
|
McpServerWithInstallInfo,
|
|
45
|
+
Metric,
|
|
46
|
+
MetricDefinition,
|
|
47
|
+
MetricSnapshot,
|
|
48
|
+
MetricSummary,
|
|
49
|
+
MetricVersion,
|
|
45
50
|
Page,
|
|
46
51
|
PageAuthMode,
|
|
47
52
|
PageContentType,
|
|
@@ -90,6 +95,7 @@ import type {
|
|
|
90
95
|
} from "../types";
|
|
91
96
|
import { FollowUpConfigSchema, isTerminalTaskStatus } from "../types";
|
|
92
97
|
import { deriveProviderFromKeyType } from "../utils/credentials";
|
|
98
|
+
import { getCurrentRequestUserId } from "../utils/request-auth-context";
|
|
93
99
|
import { scrubSecrets } from "../utils/secret-scrubber";
|
|
94
100
|
import { decryptSecret, encryptSecret, getEncryptionKey, resolveEncryptionKey } from "./crypto";
|
|
95
101
|
import { normalizeDate, normalizeDateRequired } from "./date-utils";
|
|
@@ -691,6 +697,14 @@ export function createAgent(
|
|
|
691
697
|
agent.harnessProvider ?? null,
|
|
692
698
|
);
|
|
693
699
|
if (!row) throw new Error("Failed to create agent");
|
|
700
|
+
try {
|
|
701
|
+
installSystemDefaultSkillsForAgent(id);
|
|
702
|
+
} catch (err) {
|
|
703
|
+
console.warn(
|
|
704
|
+
"[db] Failed to install system-default skills for new agent:",
|
|
705
|
+
(err as Error).message,
|
|
706
|
+
);
|
|
707
|
+
}
|
|
694
708
|
try {
|
|
695
709
|
createLogEntry({ eventType: "agent_joined", agentId: id, newValue: agent.status });
|
|
696
710
|
} catch {}
|
|
@@ -1264,6 +1278,31 @@ export function getPendingTaskForAgent(agentId: string): AgentTask | null {
|
|
|
1264
1278
|
return null;
|
|
1265
1279
|
}
|
|
1266
1280
|
|
|
1281
|
+
export function assignUnassignedTaskPending(taskId: string, agentId: string): AgentTask | null {
|
|
1282
|
+
const now = new Date().toISOString();
|
|
1283
|
+
const row = getDb()
|
|
1284
|
+
.prepare<AgentTaskRow, [string, string, string]>(
|
|
1285
|
+
`UPDATE agent_tasks SET agentId = ?, status = 'pending', lastUpdatedAt = ?
|
|
1286
|
+
WHERE id = ? AND status = 'unassigned' RETURNING *`,
|
|
1287
|
+
)
|
|
1288
|
+
.get(agentId, now, taskId);
|
|
1289
|
+
|
|
1290
|
+
if (row) {
|
|
1291
|
+
try {
|
|
1292
|
+
createLogEntry({
|
|
1293
|
+
eventType: "task_status_change",
|
|
1294
|
+
agentId,
|
|
1295
|
+
taskId,
|
|
1296
|
+
oldValue: "unassigned",
|
|
1297
|
+
newValue: "pending",
|
|
1298
|
+
metadata: { pendingDispatch: true },
|
|
1299
|
+
});
|
|
1300
|
+
} catch {}
|
|
1301
|
+
}
|
|
1302
|
+
|
|
1303
|
+
return row ? rowToAgentTask(row) : null;
|
|
1304
|
+
}
|
|
1305
|
+
|
|
1267
1306
|
export function startTask(taskId: string): AgentTask | null {
|
|
1268
1307
|
const oldTask = getTaskById(taskId);
|
|
1269
1308
|
if (!oldTask) return null;
|
|
@@ -2251,6 +2290,67 @@ export function getPausedTasksForAgent(agentId: string): AgentTask[] {
|
|
|
2251
2290
|
return rows.map(rowToAgentTask);
|
|
2252
2291
|
}
|
|
2253
2292
|
|
|
2293
|
+
export function getOrphanedInProgressTasksForAgent(
|
|
2294
|
+
agentId: string,
|
|
2295
|
+
minAgeSeconds = 60,
|
|
2296
|
+
): AgentTask[] {
|
|
2297
|
+
const cutoff = new Date(Date.now() - minAgeSeconds * 1000).toISOString();
|
|
2298
|
+
const rows = getDb()
|
|
2299
|
+
.prepare<AgentTaskRow, [string, string]>(
|
|
2300
|
+
`SELECT t.* FROM agent_tasks t
|
|
2301
|
+
LEFT JOIN active_sessions s ON s.taskId = t.id
|
|
2302
|
+
WHERE t.agentId = ?
|
|
2303
|
+
AND t.status = 'in_progress'
|
|
2304
|
+
AND t.claudeSessionId IS NULL
|
|
2305
|
+
AND t.lastUpdatedAt < ?
|
|
2306
|
+
AND s.id IS NULL
|
|
2307
|
+
AND t.finishedAt IS NULL
|
|
2308
|
+
ORDER BY t.createdAt ASC, t.rowid ASC`,
|
|
2309
|
+
)
|
|
2310
|
+
.all(agentId, cutoff);
|
|
2311
|
+
return rows.map(rowToAgentTask);
|
|
2312
|
+
}
|
|
2313
|
+
|
|
2314
|
+
export function resetOrphanedInProgressTasksForAgent(
|
|
2315
|
+
agentId: string,
|
|
2316
|
+
minAgeSeconds = 60,
|
|
2317
|
+
): AgentTask[] {
|
|
2318
|
+
const cutoff = new Date(Date.now() - minAgeSeconds * 1000).toISOString();
|
|
2319
|
+
const rows = getDb()
|
|
2320
|
+
.prepare<AgentTaskRow, [string, string]>(
|
|
2321
|
+
`UPDATE agent_tasks
|
|
2322
|
+
SET status = 'pending',
|
|
2323
|
+
lastUpdatedAt = strftime('%Y-%m-%dT%H:%M:%fZ', 'now')
|
|
2324
|
+
WHERE id IN (
|
|
2325
|
+
SELECT t.id FROM agent_tasks t
|
|
2326
|
+
LEFT JOIN active_sessions s ON s.taskId = t.id
|
|
2327
|
+
WHERE t.agentId = ?
|
|
2328
|
+
AND t.status = 'in_progress'
|
|
2329
|
+
AND t.claudeSessionId IS NULL
|
|
2330
|
+
AND t.lastUpdatedAt < ?
|
|
2331
|
+
AND s.id IS NULL
|
|
2332
|
+
AND t.finishedAt IS NULL
|
|
2333
|
+
)
|
|
2334
|
+
RETURNING *`,
|
|
2335
|
+
)
|
|
2336
|
+
.all(agentId, cutoff);
|
|
2337
|
+
|
|
2338
|
+
for (const row of rows) {
|
|
2339
|
+
try {
|
|
2340
|
+
createLogEntry({
|
|
2341
|
+
eventType: "task_status_change",
|
|
2342
|
+
taskId: row.id,
|
|
2343
|
+
agentId,
|
|
2344
|
+
oldValue: "in_progress",
|
|
2345
|
+
newValue: "pending",
|
|
2346
|
+
metadata: { orphanedInProgressRecovery: true },
|
|
2347
|
+
});
|
|
2348
|
+
} catch {}
|
|
2349
|
+
}
|
|
2350
|
+
|
|
2351
|
+
return rows.map(rowToAgentTask);
|
|
2352
|
+
}
|
|
2353
|
+
|
|
2254
2354
|
/**
|
|
2255
2355
|
* Get recently cancelled tasks for an agent.
|
|
2256
2356
|
* Used by hooks to detect task cancellation and stop the worker loop.
|
|
@@ -2858,6 +2958,7 @@ export function createTaskExtended(task: string, options?: CreateTaskOptions): A
|
|
|
2858
2958
|
}
|
|
2859
2959
|
}
|
|
2860
2960
|
|
|
2961
|
+
const auditUserId = getCurrentRequestUserId() ?? null;
|
|
2861
2962
|
const row = getDb()
|
|
2862
2963
|
.prepare<AgentTaskRow, (string | number | null)[]>(
|
|
2863
2964
|
`INSERT INTO agent_tasks (
|
|
@@ -2868,8 +2969,8 @@ export function createTaskExtended(task: string, options?: CreateTaskOptions): A
|
|
|
2868
2969
|
vcsInstallationId, vcsNodeId,
|
|
2869
2970
|
agentmailInboxId, agentmailMessageId, agentmailThreadId,
|
|
2870
2971
|
mentionMessageId, mentionChannelId, dir, parentTaskId, model, scheduleId,
|
|
2871
|
-
workflowRunId, workflowRunStepId, outputSchema, followUpConfig, requestedByUserId, contextKey, swarmVersion, createdAt, lastUpdatedAt
|
|
2872
|
-
) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?) RETURNING *`,
|
|
2972
|
+
workflowRunId, workflowRunStepId, outputSchema, followUpConfig, requestedByUserId, contextKey, swarmVersion, createdAt, lastUpdatedAt, created_by, updated_by
|
|
2973
|
+
) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?) RETURNING *`,
|
|
2873
2974
|
)
|
|
2874
2975
|
.get(
|
|
2875
2976
|
id,
|
|
@@ -2914,6 +3015,8 @@ export function createTaskExtended(task: string, options?: CreateTaskOptions): A
|
|
|
2914
3015
|
pkg.version,
|
|
2915
3016
|
now,
|
|
2916
3017
|
now,
|
|
3018
|
+
auditUserId,
|
|
3019
|
+
auditUserId,
|
|
2917
3020
|
);
|
|
2918
3021
|
|
|
2919
3022
|
if (!row) throw new Error("Failed to create task");
|
|
@@ -7204,6 +7307,234 @@ export function getPageVersion(pageId: string, version: number): PageVersion | n
|
|
|
7204
7307
|
return row ? rowToPageVersion(row) : null;
|
|
7205
7308
|
}
|
|
7206
7309
|
|
|
7310
|
+
// ============================================================================
|
|
7311
|
+
// Metrics CRUD + version history
|
|
7312
|
+
// ----------------------------------------------------------------------------
|
|
7313
|
+
// Config-driven metrics mirror Pages: parent table `metrics` holds the current
|
|
7314
|
+
// JSON definition, and `metric_versions` holds pre-update snapshots.
|
|
7315
|
+
// ============================================================================
|
|
7316
|
+
|
|
7317
|
+
type MetricRow = {
|
|
7318
|
+
id: string;
|
|
7319
|
+
agentId: string;
|
|
7320
|
+
slug: string;
|
|
7321
|
+
title: string;
|
|
7322
|
+
description: string | null;
|
|
7323
|
+
definition: string;
|
|
7324
|
+
createdAt: string;
|
|
7325
|
+
updatedAt: string;
|
|
7326
|
+
};
|
|
7327
|
+
|
|
7328
|
+
function rowToMetric(row: MetricRow): Metric {
|
|
7329
|
+
return {
|
|
7330
|
+
id: row.id,
|
|
7331
|
+
agentId: row.agentId,
|
|
7332
|
+
slug: row.slug,
|
|
7333
|
+
title: row.title,
|
|
7334
|
+
description: row.description ?? undefined,
|
|
7335
|
+
definition: JSON.parse(row.definition) as MetricDefinition,
|
|
7336
|
+
createdAt: normalizeDateRequired(row.createdAt),
|
|
7337
|
+
updatedAt: normalizeDateRequired(row.updatedAt),
|
|
7338
|
+
};
|
|
7339
|
+
}
|
|
7340
|
+
|
|
7341
|
+
function rowToMetricSummary(row: MetricRow): MetricSummary {
|
|
7342
|
+
return {
|
|
7343
|
+
id: row.id,
|
|
7344
|
+
agentId: row.agentId,
|
|
7345
|
+
slug: row.slug,
|
|
7346
|
+
title: row.title,
|
|
7347
|
+
description: row.description ?? undefined,
|
|
7348
|
+
createdAt: normalizeDateRequired(row.createdAt),
|
|
7349
|
+
updatedAt: normalizeDateRequired(row.updatedAt),
|
|
7350
|
+
};
|
|
7351
|
+
}
|
|
7352
|
+
|
|
7353
|
+
export function createMetric(data: {
|
|
7354
|
+
agentId: string;
|
|
7355
|
+
slug: string;
|
|
7356
|
+
title: string;
|
|
7357
|
+
description?: string;
|
|
7358
|
+
definition: MetricDefinition;
|
|
7359
|
+
}): Metric {
|
|
7360
|
+
const row = getDb()
|
|
7361
|
+
.prepare<MetricRow, [string, string, string, string | null, string]>(
|
|
7362
|
+
`INSERT INTO metrics (agentId, slug, title, description, definition)
|
|
7363
|
+
VALUES (?, ?, ?, ?, ?) RETURNING *`,
|
|
7364
|
+
)
|
|
7365
|
+
.get(
|
|
7366
|
+
data.agentId,
|
|
7367
|
+
data.slug,
|
|
7368
|
+
data.title,
|
|
7369
|
+
data.description ?? null,
|
|
7370
|
+
JSON.stringify(data.definition),
|
|
7371
|
+
);
|
|
7372
|
+
if (!row) throw new Error("Failed to create metric");
|
|
7373
|
+
return rowToMetric(row);
|
|
7374
|
+
}
|
|
7375
|
+
|
|
7376
|
+
export function getMetric(id: string): Metric | null {
|
|
7377
|
+
const row = getDb().prepare<MetricRow, [string]>("SELECT * FROM metrics WHERE id = ?").get(id);
|
|
7378
|
+
return row ? rowToMetric(row) : null;
|
|
7379
|
+
}
|
|
7380
|
+
|
|
7381
|
+
export function getMetricBySlug(agentId: string, slug: string): Metric | null {
|
|
7382
|
+
const row = getDb()
|
|
7383
|
+
.prepare<MetricRow, [string, string]>("SELECT * FROM metrics WHERE agentId = ? AND slug = ?")
|
|
7384
|
+
.get(agentId, slug);
|
|
7385
|
+
return row ? rowToMetric(row) : null;
|
|
7386
|
+
}
|
|
7387
|
+
|
|
7388
|
+
export function listMetricsByAgent(agentId: string, limit?: number, offset?: number): Metric[];
|
|
7389
|
+
export function listMetricsByAgent(
|
|
7390
|
+
agentId: string,
|
|
7391
|
+
limit: number | undefined,
|
|
7392
|
+
offset: number | undefined,
|
|
7393
|
+
opts: { slim: true },
|
|
7394
|
+
): MetricSummary[];
|
|
7395
|
+
export function listMetricsByAgent(
|
|
7396
|
+
agentId: string,
|
|
7397
|
+
limit = 100,
|
|
7398
|
+
offset = 0,
|
|
7399
|
+
opts?: { slim?: boolean },
|
|
7400
|
+
): Metric[] | MetricSummary[] {
|
|
7401
|
+
const rows = getDb()
|
|
7402
|
+
.prepare<MetricRow, [string, number, number]>(
|
|
7403
|
+
"SELECT * FROM metrics WHERE agentId = ? ORDER BY updatedAt DESC LIMIT ? OFFSET ?",
|
|
7404
|
+
)
|
|
7405
|
+
.all(agentId, limit, offset);
|
|
7406
|
+
return opts?.slim ? rows.map(rowToMetricSummary) : rows.map(rowToMetric);
|
|
7407
|
+
}
|
|
7408
|
+
|
|
7409
|
+
export function listAllMetrics(limit?: number, offset?: number): Metric[];
|
|
7410
|
+
export function listAllMetrics(
|
|
7411
|
+
limit: number | undefined,
|
|
7412
|
+
offset: number | undefined,
|
|
7413
|
+
opts: { slim: true },
|
|
7414
|
+
): MetricSummary[];
|
|
7415
|
+
export function listAllMetrics(
|
|
7416
|
+
limit = 100,
|
|
7417
|
+
offset = 0,
|
|
7418
|
+
opts?: { slim?: boolean },
|
|
7419
|
+
): Metric[] | MetricSummary[] {
|
|
7420
|
+
const rows = getDb()
|
|
7421
|
+
.prepare<MetricRow, [number, number]>(
|
|
7422
|
+
"SELECT * FROM metrics ORDER BY updatedAt DESC LIMIT ? OFFSET ?",
|
|
7423
|
+
)
|
|
7424
|
+
.all(limit, offset);
|
|
7425
|
+
return opts?.slim ? rows.map(rowToMetricSummary) : rows.map(rowToMetric);
|
|
7426
|
+
}
|
|
7427
|
+
|
|
7428
|
+
export function countAllMetrics(): number {
|
|
7429
|
+
const row = getDb().prepare<{ count: number }, []>("SELECT COUNT(*) AS count FROM metrics").get();
|
|
7430
|
+
return row?.count ?? 0;
|
|
7431
|
+
}
|
|
7432
|
+
|
|
7433
|
+
export function countMetricsByAgent(agentId: string): number {
|
|
7434
|
+
const row = getDb()
|
|
7435
|
+
.prepare<{ count: number }, [string]>("SELECT COUNT(*) AS count FROM metrics WHERE agentId = ?")
|
|
7436
|
+
.get(agentId);
|
|
7437
|
+
return row?.count ?? 0;
|
|
7438
|
+
}
|
|
7439
|
+
|
|
7440
|
+
export function updateMetric(
|
|
7441
|
+
id: string,
|
|
7442
|
+
data: {
|
|
7443
|
+
title?: string;
|
|
7444
|
+
description?: string | null;
|
|
7445
|
+
definition?: MetricDefinition;
|
|
7446
|
+
slug?: string;
|
|
7447
|
+
},
|
|
7448
|
+
): Metric | null {
|
|
7449
|
+
const updates: string[] = [];
|
|
7450
|
+
const params: (string | null)[] = [];
|
|
7451
|
+
if (data.title !== undefined) {
|
|
7452
|
+
updates.push("title = ?");
|
|
7453
|
+
params.push(data.title);
|
|
7454
|
+
}
|
|
7455
|
+
if (data.description !== undefined) {
|
|
7456
|
+
updates.push("description = ?");
|
|
7457
|
+
params.push(data.description ?? null);
|
|
7458
|
+
}
|
|
7459
|
+
if (data.definition !== undefined) {
|
|
7460
|
+
updates.push("definition = ?");
|
|
7461
|
+
params.push(JSON.stringify(data.definition));
|
|
7462
|
+
}
|
|
7463
|
+
if (data.slug !== undefined) {
|
|
7464
|
+
updates.push("slug = ?");
|
|
7465
|
+
params.push(data.slug);
|
|
7466
|
+
}
|
|
7467
|
+
if (updates.length === 0) return getMetric(id);
|
|
7468
|
+
updates.push("updatedAt = ?");
|
|
7469
|
+
params.push(new Date().toISOString());
|
|
7470
|
+
params.push(id);
|
|
7471
|
+
const row = getDb()
|
|
7472
|
+
.prepare<MetricRow, (string | null)[]>(
|
|
7473
|
+
`UPDATE metrics SET ${updates.join(", ")} WHERE id = ? RETURNING *`,
|
|
7474
|
+
)
|
|
7475
|
+
.get(...params);
|
|
7476
|
+
return row ? rowToMetric(row) : null;
|
|
7477
|
+
}
|
|
7478
|
+
|
|
7479
|
+
export function deleteMetric(id: string): boolean {
|
|
7480
|
+
const result = getDb().run("DELETE FROM metrics WHERE id = ?", [id]);
|
|
7481
|
+
return result.changes > 0;
|
|
7482
|
+
}
|
|
7483
|
+
|
|
7484
|
+
type MetricVersionRow = {
|
|
7485
|
+
id: string;
|
|
7486
|
+
metricId: string;
|
|
7487
|
+
version: number;
|
|
7488
|
+
snapshot: string;
|
|
7489
|
+
changedByAgentId: string | null;
|
|
7490
|
+
createdAt: string;
|
|
7491
|
+
};
|
|
7492
|
+
|
|
7493
|
+
function rowToMetricVersion(row: MetricVersionRow): MetricVersion {
|
|
7494
|
+
return {
|
|
7495
|
+
id: row.id,
|
|
7496
|
+
metricId: row.metricId,
|
|
7497
|
+
version: row.version,
|
|
7498
|
+
snapshot: JSON.parse(row.snapshot) as MetricSnapshot,
|
|
7499
|
+
changedByAgentId: row.changedByAgentId ?? undefined,
|
|
7500
|
+
createdAt: normalizeDateRequired(row.createdAt),
|
|
7501
|
+
};
|
|
7502
|
+
}
|
|
7503
|
+
|
|
7504
|
+
export function createMetricVersion(data: {
|
|
7505
|
+
metricId: string;
|
|
7506
|
+
version: number;
|
|
7507
|
+
snapshot: MetricSnapshot;
|
|
7508
|
+
changedByAgentId?: string;
|
|
7509
|
+
}): MetricVersion {
|
|
7510
|
+
const row = getDb()
|
|
7511
|
+
.prepare<MetricVersionRow, [string, number, string, string | null]>(
|
|
7512
|
+
`INSERT INTO metric_versions (metricId, version, snapshot, changedByAgentId)
|
|
7513
|
+
VALUES (?, ?, ?, ?) RETURNING *`,
|
|
7514
|
+
)
|
|
7515
|
+
.get(data.metricId, data.version, JSON.stringify(data.snapshot), data.changedByAgentId ?? null);
|
|
7516
|
+
if (!row) throw new Error("Failed to create metric version");
|
|
7517
|
+
return rowToMetricVersion(row);
|
|
7518
|
+
}
|
|
7519
|
+
|
|
7520
|
+
export function getMetricVersions(metricId: string): MetricVersion[] {
|
|
7521
|
+
return getDb()
|
|
7522
|
+
.prepare<MetricVersionRow, [string]>(
|
|
7523
|
+
"SELECT * FROM metric_versions WHERE metricId = ? ORDER BY version DESC",
|
|
7524
|
+
)
|
|
7525
|
+
.all(metricId)
|
|
7526
|
+
.map(rowToMetricVersion);
|
|
7527
|
+
}
|
|
7528
|
+
|
|
7529
|
+
export function getMetricVersion(metricId: string, version: number): MetricVersion | null {
|
|
7530
|
+
const row = getDb()
|
|
7531
|
+
.prepare<MetricVersionRow, [string, number]>(
|
|
7532
|
+
"SELECT * FROM metric_versions WHERE metricId = ? AND version = ?",
|
|
7533
|
+
)
|
|
7534
|
+
.get(metricId, version);
|
|
7535
|
+
return row ? rowToMetricVersion(row) : null;
|
|
7536
|
+
}
|
|
7537
|
+
|
|
7207
7538
|
// ============================================================================
|
|
7208
7539
|
// Prompt Template Operations
|
|
7209
7540
|
// ============================================================================
|
|
@@ -8247,6 +8578,7 @@ type SkillRow = {
|
|
|
8247
8578
|
userInvocable: number;
|
|
8248
8579
|
version: number;
|
|
8249
8580
|
isEnabled: number;
|
|
8581
|
+
systemDefault: number;
|
|
8250
8582
|
createdAt: string;
|
|
8251
8583
|
lastUpdatedAt: string;
|
|
8252
8584
|
lastFetchedAt: string | null;
|
|
@@ -8276,6 +8608,7 @@ function rowToSkill(row: SkillRow): Skill {
|
|
|
8276
8608
|
userInvocable: row.userInvocable === 1,
|
|
8277
8609
|
version: row.version,
|
|
8278
8610
|
isEnabled: row.isEnabled === 1,
|
|
8611
|
+
systemDefault: row.systemDefault === 1,
|
|
8279
8612
|
createdAt: row.createdAt,
|
|
8280
8613
|
lastUpdatedAt: row.lastUpdatedAt,
|
|
8281
8614
|
lastFetchedAt: row.lastFetchedAt,
|
|
@@ -8300,7 +8633,12 @@ function rowToAgentSkill(row: AgentSkillRow): AgentSkill {
|
|
|
8300
8633
|
};
|
|
8301
8634
|
}
|
|
8302
8635
|
|
|
8303
|
-
type SkillWithInstallRow = SkillRow & {
|
|
8636
|
+
type SkillWithInstallRow = SkillRow & {
|
|
8637
|
+
isActive: number;
|
|
8638
|
+
installedAt: string;
|
|
8639
|
+
sourceRank?: number;
|
|
8640
|
+
typeRank?: number;
|
|
8641
|
+
};
|
|
8304
8642
|
|
|
8305
8643
|
function rowToSkillWithInstall(row: SkillWithInstallRow): SkillWithInstallInfo {
|
|
8306
8644
|
return {
|
|
@@ -8330,6 +8668,7 @@ export interface SkillInsert {
|
|
|
8330
8668
|
agent?: string;
|
|
8331
8669
|
disableModelInvocation?: boolean;
|
|
8332
8670
|
userInvocable?: boolean;
|
|
8671
|
+
systemDefault?: boolean;
|
|
8333
8672
|
}
|
|
8334
8673
|
|
|
8335
8674
|
export function createSkill(data: SkillInsert): Skill {
|
|
@@ -8342,8 +8681,8 @@ export function createSkill(data: SkillInsert): Skill {
|
|
|
8342
8681
|
id, name, description, content, type, scope, ownerAgentId,
|
|
8343
8682
|
sourceUrl, sourceRepo, sourcePath, sourceBranch, sourceHash, isComplex,
|
|
8344
8683
|
allowedTools, model, effort, context, agent, disableModelInvocation, userInvocable,
|
|
8345
|
-
version, isEnabled, createdAt, lastUpdatedAt
|
|
8346
|
-
) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, 1, 1, ?, ?) RETURNING *`,
|
|
8684
|
+
version, isEnabled, systemDefault, createdAt, lastUpdatedAt
|
|
8685
|
+
) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, 1, 1, ?, ?, ?) RETURNING *`,
|
|
8347
8686
|
)
|
|
8348
8687
|
.get(
|
|
8349
8688
|
id,
|
|
@@ -8366,6 +8705,7 @@ export function createSkill(data: SkillInsert): Skill {
|
|
|
8366
8705
|
data.agent ?? null,
|
|
8367
8706
|
data.disableModelInvocation ? 1 : 0,
|
|
8368
8707
|
data.userInvocable === false ? 0 : 1,
|
|
8708
|
+
data.systemDefault ? 1 : 0,
|
|
8369
8709
|
now,
|
|
8370
8710
|
now,
|
|
8371
8711
|
);
|
|
@@ -8405,6 +8745,10 @@ export function updateSkill(
|
|
|
8405
8745
|
sets.push("isEnabled = ?");
|
|
8406
8746
|
params.push(updates.isEnabled ? 1 : 0);
|
|
8407
8747
|
}
|
|
8748
|
+
if (updates.systemDefault !== undefined) {
|
|
8749
|
+
sets.push("systemDefault = ?");
|
|
8750
|
+
params.push(updates.systemDefault ? 1 : 0);
|
|
8751
|
+
}
|
|
8408
8752
|
if (updates.allowedTools !== undefined) {
|
|
8409
8753
|
sets.push("allowedTools = ?");
|
|
8410
8754
|
params.push(updates.allowedTools ?? null);
|
|
@@ -8516,7 +8860,7 @@ export interface SkillFilters {
|
|
|
8516
8860
|
* which is replaced with an empty string so the row still satisfies `Skill`.
|
|
8517
8861
|
*/
|
|
8518
8862
|
const SKILL_SLIM_COLUMNS =
|
|
8519
|
-
"id, name, description, type, scope, ownerAgentId, sourceUrl, sourceRepo, sourcePath, sourceBranch, sourceHash, isComplex, allowedTools, model, effort, context, agent, disableModelInvocation, userInvocable, version, isEnabled, createdAt, lastUpdatedAt, lastFetchedAt, '' as content";
|
|
8863
|
+
"id, name, description, type, scope, ownerAgentId, sourceUrl, sourceRepo, sourcePath, sourceBranch, sourceHash, isComplex, allowedTools, model, effort, context, agent, disableModelInvocation, userInvocable, version, isEnabled, systemDefault, createdAt, lastUpdatedAt, lastFetchedAt, '' as content";
|
|
8520
8864
|
|
|
8521
8865
|
export function listSkills(filters?: SkillFilters): Skill[] {
|
|
8522
8866
|
const columns = filters?.includeContent === false ? SKILL_SLIM_COLUMNS : "*";
|
|
@@ -8586,6 +8930,19 @@ export function installSkill(agentId: string, skillId: string): AgentSkill {
|
|
|
8586
8930
|
return rowToAgentSkill(row);
|
|
8587
8931
|
}
|
|
8588
8932
|
|
|
8933
|
+
export function getSystemDefaultSkills(): Skill[] {
|
|
8934
|
+
return getDb()
|
|
8935
|
+
.prepare<SkillRow, []>(
|
|
8936
|
+
"SELECT * FROM skills WHERE systemDefault = 1 AND isEnabled = 1 ORDER BY name ASC",
|
|
8937
|
+
)
|
|
8938
|
+
.all()
|
|
8939
|
+
.map(rowToSkill);
|
|
8940
|
+
}
|
|
8941
|
+
|
|
8942
|
+
export function installSystemDefaultSkillsForAgent(agentId: string): AgentSkill[] {
|
|
8943
|
+
return getSystemDefaultSkills().map((skill) => installSkill(agentId, skill.id));
|
|
8944
|
+
}
|
|
8945
|
+
|
|
8589
8946
|
export function uninstallSkill(agentId: string, skillId: string): boolean {
|
|
8590
8947
|
const result = getDb()
|
|
8591
8948
|
.prepare("DELETE FROM agent_skills WHERE agentId = ? AND skillId = ?")
|
|
@@ -8595,15 +8952,23 @@ export function uninstallSkill(agentId: string, skillId: string): boolean {
|
|
|
8595
8952
|
|
|
8596
8953
|
export function getAgentSkills(agentId: string, activeOnly = true): SkillWithInstallInfo[] {
|
|
8597
8954
|
const query = `
|
|
8598
|
-
SELECT s.*, as2.isActive, as2.installedAt
|
|
8955
|
+
SELECT s.*, as2.isActive, as2.installedAt, 0 as sourceRank,
|
|
8956
|
+
CASE WHEN s.type = 'personal' THEN 0 ELSE 1 END as typeRank
|
|
8599
8957
|
FROM skills s
|
|
8600
8958
|
JOIN agent_skills as2 ON s.id = as2.skillId
|
|
8601
8959
|
WHERE as2.agentId = ?
|
|
8602
8960
|
${activeOnly ? "AND as2.isActive = 1" : ""}
|
|
8603
8961
|
AND s.isEnabled = 1
|
|
8962
|
+
UNION ALL
|
|
8963
|
+
SELECT s.*, 1 as isActive, s.createdAt as installedAt, 1 as sourceRank,
|
|
8964
|
+
CASE WHEN s.type = 'personal' THEN 0 ELSE 1 END as typeRank
|
|
8965
|
+
FROM skills s
|
|
8966
|
+
WHERE s.systemDefault = 1
|
|
8967
|
+
AND s.isEnabled = 1
|
|
8604
8968
|
ORDER BY
|
|
8605
|
-
|
|
8606
|
-
|
|
8969
|
+
sourceRank,
|
|
8970
|
+
typeRank,
|
|
8971
|
+
name
|
|
8607
8972
|
`;
|
|
8608
8973
|
|
|
8609
8974
|
const rows = getDb().prepare<SkillWithInstallRow, [string]>(query).all(agentId);
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
-- 080_skill_system_defaults.sql
|
|
2
|
+
-- Adds a first-class marker for skills that are installed for every agent.
|
|
3
|
+
-- Forward migration: add nullable-safe column with default 0.
|
|
4
|
+
-- Reverse operation, if ever needed: ALTER TABLE skills DROP COLUMN systemDefault;
|
|
5
|
+
|
|
6
|
+
ALTER TABLE skills ADD COLUMN systemDefault INTEGER NOT NULL DEFAULT 0;
|
|
7
|
+
|
|
8
|
+
CREATE INDEX IF NOT EXISTS idx_skills_system_default ON skills(systemDefault);
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
-- Config-driven metrics. Mirrors Pages: parent table holds the current
|
|
2
|
+
-- definition, metric_versions stores pre-update snapshots.
|
|
3
|
+
|
|
4
|
+
CREATE TABLE IF NOT EXISTS metrics (
|
|
5
|
+
id TEXT PRIMARY KEY DEFAULT (lower(hex(randomblob(16)))),
|
|
6
|
+
agentId TEXT NOT NULL,
|
|
7
|
+
slug TEXT NOT NULL,
|
|
8
|
+
title TEXT NOT NULL,
|
|
9
|
+
description TEXT,
|
|
10
|
+
definition TEXT NOT NULL,
|
|
11
|
+
createdAt TEXT NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
|
12
|
+
updatedAt TEXT NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
|
13
|
+
UNIQUE (agentId, slug)
|
|
14
|
+
);
|
|
15
|
+
|
|
16
|
+
CREATE INDEX IF NOT EXISTS idx_metrics_agentId ON metrics(agentId);
|
|
17
|
+
CREATE INDEX IF NOT EXISTS idx_metrics_updatedAt ON metrics(updatedAt DESC);
|
|
18
|
+
|
|
19
|
+
CREATE TABLE IF NOT EXISTS metric_versions (
|
|
20
|
+
id TEXT PRIMARY KEY DEFAULT (lower(hex(randomblob(16)))),
|
|
21
|
+
metricId TEXT NOT NULL REFERENCES metrics(id) ON DELETE CASCADE,
|
|
22
|
+
version INTEGER NOT NULL,
|
|
23
|
+
snapshot TEXT NOT NULL,
|
|
24
|
+
changedByAgentId TEXT,
|
|
25
|
+
createdAt TEXT NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
|
26
|
+
UNIQUE (metricId, version)
|
|
27
|
+
);
|
|
28
|
+
|
|
29
|
+
CREATE INDEX IF NOT EXISTS idx_metric_versions_metricId ON metric_versions(metricId);
|
|
30
|
+
|
|
31
|
+
INSERT OR IGNORE INTO metrics (agentId, slug, title, description, definition)
|
|
32
|
+
VALUES
|
|
33
|
+
(
|
|
34
|
+
'system',
|
|
35
|
+
'swarm-operations-overview',
|
|
36
|
+
'Swarm operations overview',
|
|
37
|
+
'A starter dashboard mixing raw SQL widgets with chart and table visualizations.',
|
|
38
|
+
'{"version":1,"refreshSeconds":60,"layout":{"columns":2},"variables":[{"key":"rangeModifier","label":"Time range","type":"select","defaultValue":"-30 days","options":[{"label":"Last 7 days","value":"-7 days"},{"label":"Last 30 days","value":"-30 days"},{"label":"Last 90 days","value":"-90 days"}]},{"key":"userFilter","label":"Requester user ID or name","type":"text","defaultValue":""},{"key":"agentFilter","label":"Agent ID","type":"text","defaultValue":""}],"widgets":[{"id":"open-tasks","title":"Open tasks","description":"Tasks that are not terminal.","query":{"sql":"SELECT COUNT(*) AS open_tasks FROM agent_tasks WHERE status NOT IN (''completed'', ''failed'', ''cancelled'', ''superseded'')","maxRows":10},"viz":{"type":"stat","value":"open_tasks","format":"integer"}},{"id":"tasks-created-per-day","title":"Tasks created per day","description":"Daily task volume for the selected time range.","query":{"sql":"SELECT date(createdAt) AS day, COUNT(*) AS tasks FROM agent_tasks WHERE createdAt >= datetime(''now'', ?) GROUP BY day ORDER BY day","params":["{{rangeModifier}}"],"maxRows":100},"viz":{"type":"line","x":"day","y":"tasks","format":"integer","columns":[{"key":"day","label":"Day"},{"key":"tasks","label":"Tasks","format":"integer"}]}},{"id":"usage-by-user","title":"Usage by user","description":"Tasks requested and session cost by user for the selected time range, requester filter, and agent filter.","query":{"sql":"SELECT COALESCE(u.name, ''Unassigned'') AS user, COUNT(DISTINCT t.id) AS tasks, ROUND(COALESCE(SUM(sc.totalCostUsd), 0), 4) AS cost_usd FROM agent_tasks t LEFT JOIN users u ON u.id = t.requestedByUserId LEFT JOIN session_costs sc ON sc.taskId = t.id WHERE t.createdAt >= datetime(''now'', ?) AND (? = '''' OR COALESCE(u.id, '''') = ? OR COALESCE(u.name, '''') LIKE ''%'' || ? || ''%'') AND (? = '''' OR COALESCE(t.agentId, '''') = ?) GROUP BY COALESCE(u.name, ''Unassigned'') ORDER BY cost_usd DESC, tasks DESC","params":["{{rangeModifier}}","{{userFilter}}","{{userFilter}}","{{userFilter}}","{{agentFilter}}","{{agentFilter}}"],"maxRows":100},"viz":{"type":"bar","x":"user","y":"tasks","format":"integer","columns":[{"key":"user","label":"User"},{"key":"tasks","label":"Tasks","format":"integer"},{"key":"cost_usd","label":"Cost","format":"currency"}]}},{"id":"task-outcomes-by-day","title":"Task outcomes by day","description":"Completed and failed tasks for the selected time range.","query":{"sql":"SELECT date(finishedAt) AS day, SUM(CASE WHEN status = ''completed'' THEN 1 ELSE 0 END) AS completed, SUM(CASE WHEN status = ''failed'' THEN 1 ELSE 0 END) AS failed FROM agent_tasks WHERE finishedAt IS NOT NULL AND finishedAt >= datetime(''now'', ?) GROUP BY day ORDER BY day","params":["{{rangeModifier}}"],"maxRows":100},"viz":{"type":"multi-line","x":"day","series":["completed","failed"],"format":"integer","columns":[{"key":"day","label":"Day"},{"key":"completed","label":"Completed","format":"integer"},{"key":"failed","label":"Failed","format":"integer"}]}},{"id":"recent-task-outcomes","title":"Recent task outcomes","description":"Task status breakdown for tasks created in the selected time range.","query":{"sql":"SELECT status, COUNT(*) AS tasks FROM agent_tasks WHERE createdAt >= datetime(''now'', ?) GROUP BY status ORDER BY tasks DESC","params":["{{rangeModifier}}"],"maxRows":100},"viz":{"type":"table","columns":[{"key":"status","label":"Status"},{"key":"tasks","label":"Tasks","format":"integer"}]}}]}'
|
|
39
|
+
);
|
|
@@ -0,0 +1,120 @@
|
|
|
1
|
+
-- Add nullable user audit columns to mutable/user-facing tables.
|
|
2
|
+
-- Existing rows and system-originated writes remain NULL.
|
|
3
|
+
|
|
4
|
+
ALTER TABLE agents ADD COLUMN created_by TEXT REFERENCES users(id);
|
|
5
|
+
ALTER TABLE agents ADD COLUMN updated_by TEXT REFERENCES users(id);
|
|
6
|
+
|
|
7
|
+
ALTER TABLE channels ADD COLUMN created_by TEXT REFERENCES users(id);
|
|
8
|
+
ALTER TABLE channels ADD COLUMN updated_by TEXT REFERENCES users(id);
|
|
9
|
+
|
|
10
|
+
ALTER TABLE agent_tasks ADD COLUMN created_by TEXT REFERENCES users(id);
|
|
11
|
+
ALTER TABLE agent_tasks ADD COLUMN updated_by TEXT REFERENCES users(id);
|
|
12
|
+
|
|
13
|
+
ALTER TABLE channel_messages ADD COLUMN created_by TEXT REFERENCES users(id);
|
|
14
|
+
ALTER TABLE channel_messages ADD COLUMN updated_by TEXT REFERENCES users(id);
|
|
15
|
+
|
|
16
|
+
ALTER TABLE services ADD COLUMN created_by TEXT REFERENCES users(id);
|
|
17
|
+
ALTER TABLE services ADD COLUMN updated_by TEXT REFERENCES users(id);
|
|
18
|
+
|
|
19
|
+
ALTER TABLE inbox_messages ADD COLUMN created_by TEXT REFERENCES users(id);
|
|
20
|
+
ALTER TABLE inbox_messages ADD COLUMN updated_by TEXT REFERENCES users(id);
|
|
21
|
+
|
|
22
|
+
ALTER TABLE scheduled_tasks ADD COLUMN created_by TEXT REFERENCES users(id);
|
|
23
|
+
ALTER TABLE scheduled_tasks ADD COLUMN updated_by TEXT REFERENCES users(id);
|
|
24
|
+
|
|
25
|
+
ALTER TABLE swarm_config ADD COLUMN created_by TEXT REFERENCES users(id);
|
|
26
|
+
ALTER TABLE swarm_config ADD COLUMN updated_by TEXT REFERENCES users(id);
|
|
27
|
+
|
|
28
|
+
ALTER TABLE swarm_repos ADD COLUMN created_by TEXT REFERENCES users(id);
|
|
29
|
+
ALTER TABLE swarm_repos ADD COLUMN updated_by TEXT REFERENCES users(id);
|
|
30
|
+
|
|
31
|
+
ALTER TABLE agent_memory ADD COLUMN created_by TEXT REFERENCES users(id);
|
|
32
|
+
ALTER TABLE agent_memory ADD COLUMN updated_by TEXT REFERENCES users(id);
|
|
33
|
+
|
|
34
|
+
ALTER TABLE agentmail_inbox_mappings ADD COLUMN created_by TEXT REFERENCES users(id);
|
|
35
|
+
ALTER TABLE agentmail_inbox_mappings ADD COLUMN updated_by TEXT REFERENCES users(id);
|
|
36
|
+
|
|
37
|
+
ALTER TABLE workflows ADD COLUMN created_by TEXT REFERENCES users(id);
|
|
38
|
+
ALTER TABLE workflows ADD COLUMN updated_by TEXT REFERENCES users(id);
|
|
39
|
+
|
|
40
|
+
ALTER TABLE workflow_runs ADD COLUMN created_by TEXT REFERENCES users(id);
|
|
41
|
+
ALTER TABLE workflow_runs ADD COLUMN updated_by TEXT REFERENCES users(id);
|
|
42
|
+
|
|
43
|
+
ALTER TABLE workflow_run_steps ADD COLUMN created_by TEXT REFERENCES users(id);
|
|
44
|
+
ALTER TABLE workflow_run_steps ADD COLUMN updated_by TEXT REFERENCES users(id);
|
|
45
|
+
|
|
46
|
+
ALTER TABLE workflow_versions ADD COLUMN created_by TEXT REFERENCES users(id);
|
|
47
|
+
ALTER TABLE workflow_versions ADD COLUMN updated_by TEXT REFERENCES users(id);
|
|
48
|
+
|
|
49
|
+
ALTER TABLE prompt_templates ADD COLUMN created_by TEXT REFERENCES users(id);
|
|
50
|
+
ALTER TABLE prompt_templates ADD COLUMN updated_by TEXT REFERENCES users(id);
|
|
51
|
+
|
|
52
|
+
ALTER TABLE prompt_template_history ADD COLUMN created_by TEXT REFERENCES users(id);
|
|
53
|
+
ALTER TABLE prompt_template_history ADD COLUMN updated_by TEXT REFERENCES users(id);
|
|
54
|
+
|
|
55
|
+
ALTER TABLE approval_requests ADD COLUMN created_by TEXT REFERENCES users(id);
|
|
56
|
+
ALTER TABLE approval_requests ADD COLUMN updated_by TEXT REFERENCES users(id);
|
|
57
|
+
|
|
58
|
+
ALTER TABLE mcp_servers ADD COLUMN created_by TEXT REFERENCES users(id);
|
|
59
|
+
ALTER TABLE mcp_servers ADD COLUMN updated_by TEXT REFERENCES users(id);
|
|
60
|
+
|
|
61
|
+
ALTER TABLE mcp_oauth_tokens ADD COLUMN created_by TEXT REFERENCES users(id);
|
|
62
|
+
ALTER TABLE mcp_oauth_tokens ADD COLUMN updated_by TEXT REFERENCES users(id);
|
|
63
|
+
|
|
64
|
+
ALTER TABLE mcp_oauth_pending ADD COLUMN created_by TEXT REFERENCES users(id);
|
|
65
|
+
ALTER TABLE mcp_oauth_pending ADD COLUMN updated_by TEXT REFERENCES users(id);
|
|
66
|
+
|
|
67
|
+
ALTER TABLE task_templates ADD COLUMN created_by TEXT REFERENCES users(id);
|
|
68
|
+
ALTER TABLE task_templates ADD COLUMN updated_by TEXT REFERENCES users(id);
|
|
69
|
+
|
|
70
|
+
ALTER TABLE pages ADD COLUMN created_by TEXT REFERENCES users(id);
|
|
71
|
+
ALTER TABLE pages ADD COLUMN updated_by TEXT REFERENCES users(id);
|
|
72
|
+
|
|
73
|
+
ALTER TABLE page_versions ADD COLUMN created_by TEXT REFERENCES users(id);
|
|
74
|
+
ALTER TABLE page_versions ADD COLUMN updated_by TEXT REFERENCES users(id);
|
|
75
|
+
|
|
76
|
+
ALTER TABLE kv_entries ADD COLUMN created_by TEXT REFERENCES users(id);
|
|
77
|
+
ALTER TABLE kv_entries ADD COLUMN updated_by TEXT REFERENCES users(id);
|
|
78
|
+
|
|
79
|
+
ALTER TABLE scripts ADD COLUMN created_by TEXT REFERENCES users(id);
|
|
80
|
+
ALTER TABLE scripts ADD COLUMN updated_by TEXT REFERENCES users(id);
|
|
81
|
+
|
|
82
|
+
ALTER TABLE script_versions ADD COLUMN created_by TEXT REFERENCES users(id);
|
|
83
|
+
ALTER TABLE script_versions ADD COLUMN updated_by TEXT REFERENCES users(id);
|
|
84
|
+
|
|
85
|
+
ALTER TABLE skills ADD COLUMN created_by TEXT REFERENCES users(id);
|
|
86
|
+
ALTER TABLE skills ADD COLUMN updated_by TEXT REFERENCES users(id);
|
|
87
|
+
|
|
88
|
+
ALTER TABLE users ADD COLUMN created_by TEXT REFERENCES users(id);
|
|
89
|
+
ALTER TABLE users ADD COLUMN updated_by TEXT REFERENCES users(id);
|
|
90
|
+
|
|
91
|
+
ALTER TABLE user_external_ids ADD COLUMN created_by TEXT REFERENCES users(id);
|
|
92
|
+
ALTER TABLE user_external_ids ADD COLUMN updated_by TEXT REFERENCES users(id);
|
|
93
|
+
|
|
94
|
+
ALTER TABLE user_tokens ADD COLUMN created_by TEXT REFERENCES users(id);
|
|
95
|
+
ALTER TABLE user_tokens ADD COLUMN updated_by TEXT REFERENCES users(id);
|
|
96
|
+
|
|
97
|
+
ALTER TABLE task_attachments ADD COLUMN created_by TEXT REFERENCES users(id);
|
|
98
|
+
ALTER TABLE task_attachments ADD COLUMN updated_by TEXT REFERENCES users(id);
|
|
99
|
+
|
|
100
|
+
ALTER TABLE budgets ADD COLUMN created_by TEXT REFERENCES users(id);
|
|
101
|
+
ALTER TABLE budgets ADD COLUMN updated_by TEXT REFERENCES users(id);
|
|
102
|
+
|
|
103
|
+
ALTER TABLE pricing ADD COLUMN created_by TEXT REFERENCES users(id);
|
|
104
|
+
ALTER TABLE pricing ADD COLUMN updated_by TEXT REFERENCES users(id);
|
|
105
|
+
|
|
106
|
+
ALTER TABLE inbox_item_state ADD COLUMN created_by TEXT REFERENCES users(id);
|
|
107
|
+
ALTER TABLE inbox_item_state ADD COLUMN updated_by TEXT REFERENCES users(id);
|
|
108
|
+
|
|
109
|
+
ALTER TABLE metrics ADD COLUMN created_by TEXT REFERENCES users(id);
|
|
110
|
+
ALTER TABLE metrics ADD COLUMN updated_by TEXT REFERENCES users(id);
|
|
111
|
+
|
|
112
|
+
ALTER TABLE metric_versions ADD COLUMN created_by TEXT REFERENCES users(id);
|
|
113
|
+
ALTER TABLE metric_versions ADD COLUMN updated_by TEXT REFERENCES users(id);
|
|
114
|
+
|
|
115
|
+
CREATE INDEX IF NOT EXISTS idx_agent_tasks_created_by ON agent_tasks(created_by) WHERE created_by IS NOT NULL;
|
|
116
|
+
CREATE INDEX IF NOT EXISTS idx_agent_tasks_updated_by ON agent_tasks(updated_by) WHERE updated_by IS NOT NULL;
|
|
117
|
+
CREATE INDEX IF NOT EXISTS idx_workflows_created_by ON workflows(created_by) WHERE created_by IS NOT NULL;
|
|
118
|
+
CREATE INDEX IF NOT EXISTS idx_pages_created_by ON pages(created_by) WHERE created_by IS NOT NULL;
|
|
119
|
+
CREATE INDEX IF NOT EXISTS idx_scripts_created_by ON scripts(created_by) WHERE created_by IS NOT NULL;
|
|
120
|
+
CREATE INDEX IF NOT EXISTS idx_skills_created_by ON skills(created_by) WHERE created_by IS NOT NULL;
|