@capybara-hq/kernel 0.1.0-rc.26 → 0.1.0-rc.28
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/dist/app.js +2 -0
- package/dist/catalog/catalog-content.d.ts +18 -1
- package/dist/catalog/catalog-content.js +5 -2
- package/dist/catalog/catalog-scope.service.js +3 -2
- package/dist/catalog/marketplaces.service.d.ts +1 -1
- package/dist/catalog/org-catalog.service.js +13 -3
- package/dist/catalog/plugin-install.d.ts +37 -16
- package/dist/catalog/plugin-install.js +108 -34
- package/dist/catalog/plugin-upgrade.js +1 -0
- package/dist/channels/actions.d.ts +4 -1
- package/dist/channels/actions.js +5 -2
- package/dist/channels/cards.d.ts +7 -1
- package/dist/channels/cards.js +28 -1
- package/dist/channels/phrases.d.ts +15 -0
- package/dist/channels/phrases.js +9 -0
- package/dist/config/schema.d.ts +8 -0
- package/dist/config/schema.js +69 -0
- package/dist/conversations/events.d.ts +14 -0
- package/dist/conversations/events.js +20 -0
- package/dist/db/kernel-schema.d.ts +19 -4
- package/dist/errors.d.ts +5 -0
- package/dist/errors.js +5 -0
- package/dist/git/gateway.d.ts +93 -0
- package/dist/git/gateway.js +750 -0
- package/dist/git/gateway.route.d.ts +16 -0
- package/dist/git/gateway.route.js +41 -0
- package/dist/git/git.module.d.ts +10 -0
- package/dist/git/git.module.js +31 -0
- package/dist/git/identity.d.ts +80 -0
- package/dist/git/identity.js +209 -0
- package/dist/git/pkt-line.d.ts +53 -0
- package/dist/git/pkt-line.js +146 -0
- package/dist/git/run-end.d.ts +29 -0
- package/dist/git/run-end.js +121 -0
- package/dist/git/sources.d.ts +42 -0
- package/dist/git/sources.js +134 -0
- package/dist/git/tickets.d.ts +69 -0
- package/dist/git/tickets.js +194 -0
- package/dist/http/api.module.js +3 -0
- package/dist/http/app.d.ts +6 -0
- package/dist/http/app.js +3 -0
- package/dist/infra/config/kernel-config.service.js +2 -0
- package/dist/orgs/settings.service.d.ts +21 -0
- package/dist/orgs/settings.service.js +18 -0
- package/dist/overrides.d.ts +6 -0
- package/dist/overrides.js +4 -0
- package/dist/platform/exclusions.js +3 -0
- package/dist/runtime/run-finish.d.ts +5 -0
- package/dist/runtime/run-finish.js +12 -3
- package/dist/runtime/runtime.module.js +2 -0
- package/dist/runtime/waits.js +7 -5
- package/dist/schedules/fire.d.ts +3 -3
- package/dist/schedules/fire.js +7 -4
- package/dist/schedules/grant-rules.d.ts +40 -0
- package/dist/schedules/grant-rules.js +83 -0
- package/dist/schedules/scheduled-tasks.service.d.ts +9 -7
- package/dist/schedules/scheduled-tasks.service.js +50 -15
- package/dist/schedules/types.d.ts +2 -0
- package/dist/tools/approvals.service.d.ts +100 -19
- package/dist/tools/approvals.service.js +288 -21
- package/dist/tools/builtin-names.d.ts +4 -2
- package/dist/tools/builtin-names.js +6 -1
- package/dist/tools/builtins/schedules.d.ts +11 -9
- package/dist/tools/builtins/schedules.js +202 -44
- package/dist/tools/connector-account-policies.d.ts +8 -0
- package/dist/tools/connector-account-policies.js +8 -0
- package/dist/tools/connectors.controller.d.ts +2 -0
- package/dist/tools/connectors.controller.js +5 -1
- package/dist/tools/connectors.service.d.ts +46 -3
- package/dist/tools/connectors.service.js +98 -9
- package/dist/tools/credentials.d.ts +18 -0
- package/dist/tools/credentials.js +60 -0
- package/dist/tools/credentials.module.d.ts +7 -0
- package/dist/tools/credentials.module.js +22 -0
- package/dist/tools/git-asks.d.ts +113 -0
- package/dist/tools/git-asks.js +174 -0
- package/dist/tools/git-push-policy.d.ts +89 -0
- package/dist/tools/git-push-policy.js +175 -0
- package/dist/tools/info.d.ts +3 -3
- package/dist/tools/info.js +3 -3
- package/dist/tools/network-asks.d.ts +5 -0
- package/dist/tools/network-asks.js +9 -2
- package/dist/tools/tools.module.js +4 -3
- package/package.json +3 -3
- package/src/migrations/0126_git_gateway.sql +10 -0
- package/src/migrations/0127_git_push_policy.sql +12 -0
- package/src/migrations/0128_scheduled_task_plugin_disabled.sql +10 -0
- package/src/migrations/0129_connector_plugin_disabled.sql +5 -0
|
@@ -14,6 +14,7 @@ import { AgentLookup } from "../agents/agent-lookup.js";
|
|
|
14
14
|
import { ConversationAccess } from "../conversations/access.js";
|
|
15
15
|
import { readMessageContext } from "../conversations/message-context.js";
|
|
16
16
|
import { ApiError } from "../errors.js";
|
|
17
|
+
import { enabledExtensionsByOrg, isExtensionEnabled } from "../extensions/enabled.js";
|
|
17
18
|
import { ExtensionRegistry } from "../extensions/registry.js";
|
|
18
19
|
import { audit } from "../identity/audit.js";
|
|
19
20
|
import { KernelConfigService } from "../infra/config/kernel-config.service.js";
|
|
@@ -33,7 +34,7 @@ import { ToolRegistry } from "../tools/registry.js";
|
|
|
33
34
|
import { assembleCalendar, CALENDAR_LIMITS, CALENDAR_RANGE_DAYS, CALENDAR_TASK_RANGE_DAYS, calendarRunReadLimit, } from "./calendar.js";
|
|
34
35
|
import { readScheduleSettings } from "./effective-settings.js";
|
|
35
36
|
import { grantNotAllowed, scheduleDisabled, scheduleForbidden, scheduleNotFound, targetInvalid, } from "./errors.js";
|
|
36
|
-
import { grantRefusal, grantRefusalOf, isNetworkGrantKey, isPolicyGrantKey, isTierGrantKey, NETWORK_GRANT_PREFIX, NETWORK_GRANT_SPEC_HASH, networkGrantHost, networkGrantRefusal, TIER_GRANT_SPEC_HASH, tierGrantRefusal, } from "./grant-rules.js";
|
|
37
|
+
import { GIT_GRANT_SPEC_HASH, GIT_PUSH_GRANT, gitGrantRefusal, grantRefusal, grantRefusalOf, isGitGrantKey, isNetworkGrantKey, isPolicyGrantKey, isTierGrantKey, NETWORK_GRANT_PREFIX, NETWORK_GRANT_SPEC_HASH, networkGrantHost, networkGrantRefusal, normalizeGitGrantKey, TIER_GRANT_SPEC_HASH, tierGrantRefusal, } from "./grant-rules.js";
|
|
37
38
|
import { oweSchedFire, oweSchedSettleUnfired } from "./job-ids.js";
|
|
38
39
|
import { pauseTaskIn } from "./pause.js";
|
|
39
40
|
import { jitterForGap, minGapMinutes, nextTick, validateTrigger } from "./schedule-math.js";
|
|
@@ -41,8 +42,15 @@ import { ScheduledTaskStore } from "./store.js";
|
|
|
41
42
|
export { grantRefusal, grantRefusalOf, networkGrantRefusal, };
|
|
42
43
|
/** The refusal of a network grant written outside a person's web session. */
|
|
43
44
|
const NETWORK_GRANT_NEEDS_PERSON = "Network domains are approved on the task page by a person.";
|
|
45
|
+
/** Why a git push grant needs a person (sandbox git credentials spec §7). */
|
|
46
|
+
const GIT_GRANT_NEEDS_PERSON = "Git pushes are approved on the task page by a person.";
|
|
44
47
|
/** The refusal of a sandbox tier grant written outside a person's web session. */
|
|
45
48
|
const TIER_GRANT_NEEDS_PERSON = "A sandbox level is approved on the task page by a person.";
|
|
49
|
+
/**
|
|
50
|
+
* A grant that belongs to no tool: a network domain, a git push or a sandbox tier (never stale,
|
|
51
|
+
* never re-resolved).
|
|
52
|
+
*/
|
|
53
|
+
const isNonToolGrantKey = (key) => isPolicyGrantKey(key) || isGitGrantKey(key);
|
|
46
54
|
const RUNS_DEFAULT = 50;
|
|
47
55
|
const RUNS_MAX = 200;
|
|
48
56
|
const DAY_MS = 86_400_000;
|
|
@@ -194,8 +202,8 @@ let ScheduledTasksService = class ScheduledTasksService {
|
|
|
194
202
|
changes.agentId = agent.id;
|
|
195
203
|
// the grants were approved for the old agent's tools: each must hold for the new agent
|
|
196
204
|
// too (refused, so the creator sees which), and takes the new agent's definition; network
|
|
197
|
-
// and sandbox tier grants belong to no tool and stay as they are
|
|
198
|
-
const held = (await this.store.listGrants(t, task.id)).filter((g) => !
|
|
205
|
+
// and git and sandbox tier grants belong to no tool and stay as they are
|
|
206
|
+
const held = (await this.store.listGrants(t, task.id)).filter((g) => !isNonToolGrantKey(g.toolKey));
|
|
199
207
|
const regranted = await this.resolveGrants(orgId, role, agent, settings, held.map((g) => ({
|
|
200
208
|
toolKey: g.toolKey,
|
|
201
209
|
...(g.connectorId !== null && { connectorId: g.connectorId }),
|
|
@@ -465,15 +473,18 @@ let ScheduledTasksService = class ScheduledTasksService {
|
|
|
465
473
|
});
|
|
466
474
|
}
|
|
467
475
|
/**
|
|
468
|
-
* The chats the caller can point a `chat` task at (spec §8): per active connection of the org
|
|
469
|
-
* their DM threads (archived included) and, on a channel with
|
|
470
|
-
* thread in. Members up (`schedules.use`, the route's).
|
|
476
|
+
* The chats the caller can point a `chat` task at (spec §8): per active connection of the org
|
|
477
|
+
* whose extension is enabled in it, their DM threads (archived included) and, on a channel with
|
|
478
|
+
* threads, the groups they have a thread in. Members up (`schedules.use`, the route's).
|
|
471
479
|
*/
|
|
472
480
|
async chatTargets(orgId, accountId) {
|
|
473
481
|
await this.liveRole(orgId, accountId);
|
|
474
482
|
const rows = await this.db.db
|
|
475
483
|
.selectFrom("channel_threads")
|
|
476
484
|
.innerJoin("channel_connections", "channel_connections.id", "channel_threads.connection_id")
|
|
485
|
+
.innerJoin(enabledExtensionsByOrg(this.db.db).as("en"), (j) => j
|
|
486
|
+
.onRef("en.org_id", "=", "channel_connections.org_id")
|
|
487
|
+
.onRef("en.plugin", "=", "channel_connections.plugin"))
|
|
477
488
|
.select([
|
|
478
489
|
"channel_connections.id as connection_id",
|
|
479
490
|
"channel_connections.name",
|
|
@@ -556,13 +567,13 @@ let ScheduledTasksService = class ScheduledTasksService {
|
|
|
556
567
|
return [];
|
|
557
568
|
// the creator's view of the agent's tools: a grant whose tool changed or left is stale;
|
|
558
569
|
// unknown (null) when the tools cannot be read now, rather than failing the task page
|
|
559
|
-
const current = grants.every((g) =>
|
|
570
|
+
const current = grants.every((g) => isNonToolGrantKey(g.toolKey))
|
|
560
571
|
? new Map()
|
|
561
572
|
: await this.agentToolFacts(orgId, task.accountId, task.agentId);
|
|
562
573
|
return grants.map((g) => ({
|
|
563
574
|
...g,
|
|
564
|
-
// a network or sandbox tier grant names no tool definition: never stale
|
|
565
|
-
stale:
|
|
575
|
+
// a network, git or sandbox tier grant names no tool definition: never stale
|
|
576
|
+
stale: isNonToolGrantKey(g.toolKey)
|
|
566
577
|
? false
|
|
567
578
|
: current === null
|
|
568
579
|
? null
|
|
@@ -716,8 +727,9 @@ let ScheduledTasksService = class ScheduledTasksService {
|
|
|
716
727
|
// a refused tool granted since drops out, unless its grant no longer matches the tool's
|
|
717
728
|
// definition (stale: it would be refused again); a refused domain granted since drops out
|
|
718
729
|
// while the org's network allowlist admits it (network ask-to-allow spec §8.3)
|
|
730
|
+
// a refused git push drops out once the task holds a grant for it or for every repository;
|
|
719
731
|
// a refused sandbox level granted since drops out while the org's ceiling is still open
|
|
720
|
-
const isTool = (k) => !k.startsWith("connection:") && !
|
|
732
|
+
const isTool = (k) => !k.startsWith("connection:") && !isNonToolGrantKey(k);
|
|
721
733
|
const facts = refused.some(isTool) ? await toolsOf(task.agentId) : null;
|
|
722
734
|
const limits = refused.some(isNetworkGrantKey) ? await orgLimits() : null;
|
|
723
735
|
const open = refused.some(isTierGrantKey) ? await openReachable() : false;
|
|
@@ -726,6 +738,8 @@ let ScheduledTasksService = class ScheduledTasksService {
|
|
|
726
738
|
const hash = have?.get(k);
|
|
727
739
|
if (isPolicyGrantKey(k))
|
|
728
740
|
return hash === undefined || !admits(k);
|
|
741
|
+
if (isGitGrantKey(k))
|
|
742
|
+
return hash === undefined && have?.get(GIT_PUSH_GRANT) === undefined;
|
|
729
743
|
if (hash === undefined)
|
|
730
744
|
return true;
|
|
731
745
|
const current = facts?.get(k);
|
|
@@ -905,9 +919,9 @@ let ScheduledTasksService = class ScheduledTasksService {
|
|
|
905
919
|
* - the mode and its fields agree (`conversation`: a conversation and no chat; `chat`: a chat
|
|
906
920
|
* and no conversation; `new`: neither);
|
|
907
921
|
* - `conversation`: the creator's live chat conversation with this agent, still accessible;
|
|
908
|
-
* - `chat`: the connection is active
|
|
909
|
-
*
|
|
910
|
-
* and a channel with threads.
|
|
922
|
+
* - `chat`: the connection is active, its channel extension is enabled in this org, and it is
|
|
923
|
+
* bound to this agent; a DM needs a thread row (archived allowed) of the creator in that chat;
|
|
924
|
+
* a group needs the creator's thread row in the group and a channel with threads.
|
|
911
925
|
*/
|
|
912
926
|
async checkTarget(orgId, accountId, agentId, target) {
|
|
913
927
|
const { mode, conversationId, chat } = target;
|
|
@@ -947,6 +961,9 @@ let ScheduledTasksService = class ScheduledTasksService {
|
|
|
947
961
|
if (conn?.status !== "active") {
|
|
948
962
|
throw targetInvalid("The channel connection does not exist or is not active");
|
|
949
963
|
}
|
|
964
|
+
if (!(await isExtensionEnabled(t, orgId, conn.plugin))) {
|
|
965
|
+
throw targetInvalid("The channel's extension is disabled in this organization, so its chats cannot receive a task's runs");
|
|
966
|
+
}
|
|
950
967
|
if (conn.agent_id !== agentId) {
|
|
951
968
|
throw targetInvalid("The chat belongs to another agent: use the connection's agent");
|
|
952
969
|
}
|
|
@@ -1029,7 +1046,9 @@ let ScheduledTasksService = class ScheduledTasksService {
|
|
|
1029
1046
|
* `deviceId`, the task's device (null: none can be determined, the device rule is skipped),
|
|
1030
1047
|
* stored with `spec_hash` `network` and no connector (plan P-D7), and only when
|
|
1031
1048
|
* `source.fromSession` (a person on the task page; never a token, the Platform tool or the
|
|
1032
|
-
* schedule tools).
|
|
1049
|
+
* schedule tools). Each git push key (`git:push`, `git:push:<owner>/<repo>`, the repository
|
|
1050
|
+
* lower-cased) is refused by {@link gitGrantRefusal} and stored with `spec_hash` `git` and no
|
|
1051
|
+
* connector, also only when `source.fromSession`. Duplicates keep the last.
|
|
1033
1052
|
*/
|
|
1034
1053
|
async resolveGrants(orgId, role, agent, settings, grants, deviceId, source = {}) {
|
|
1035
1054
|
if (grants.length === 0)
|
|
@@ -1052,6 +1071,22 @@ let ScheduledTasksService = class ScheduledTasksService {
|
|
|
1052
1071
|
out.set(toolKey, { toolKey, specHash: NETWORK_GRANT_SPEC_HASH, connectorId: null });
|
|
1053
1072
|
}
|
|
1054
1073
|
}
|
|
1074
|
+
const git = grants.filter((g) => isGitGrantKey(g.toolKey));
|
|
1075
|
+
if (git.length > 0) {
|
|
1076
|
+
// a push is the creator's decision, never an agent's or a token's (as network domains)
|
|
1077
|
+
if (source.fromSession !== true)
|
|
1078
|
+
throw grantNotAllowed(GIT_GRANT_NEEDS_PERSON);
|
|
1079
|
+
for (const g of git) {
|
|
1080
|
+
if (g.connectorId !== undefined) {
|
|
1081
|
+
throw grantNotAllowed(`${g.toolKey} is a git push and comes from no connector`);
|
|
1082
|
+
}
|
|
1083
|
+
const toolKey = normalizeGitGrantKey(g.toolKey);
|
|
1084
|
+
const why = gitGrantRefusal(toolKey, { forbiddenTools: settings.forbiddenTools });
|
|
1085
|
+
if (why !== null)
|
|
1086
|
+
throw grantNotAllowed(why.message);
|
|
1087
|
+
out.set(toolKey, { toolKey, specHash: GIT_GRANT_SPEC_HASH, connectorId: null });
|
|
1088
|
+
}
|
|
1089
|
+
}
|
|
1055
1090
|
const tiers = grants.filter((g) => isTierGrantKey(g.toolKey));
|
|
1056
1091
|
if (tiers.length > 0) {
|
|
1057
1092
|
if (source.fromSession !== true)
|
|
@@ -1076,7 +1111,7 @@ let ScheduledTasksService = class ScheduledTasksService {
|
|
|
1076
1111
|
});
|
|
1077
1112
|
}
|
|
1078
1113
|
}
|
|
1079
|
-
const toolGrants = grants.filter((g) => !
|
|
1114
|
+
const toolGrants = grants.filter((g) => !isNonToolGrantKey(g.toolKey));
|
|
1080
1115
|
if (toolGrants.length === 0)
|
|
1081
1116
|
return [...out.values()];
|
|
1082
1117
|
const d = agent.definition;
|
|
@@ -28,6 +28,8 @@ export type SchedulePauseReason = "creator" | "admin" | "failures" | "creator_in
|
|
|
28
28
|
| "invalid_schedule";
|
|
29
29
|
export type TaskRunStatus = "pending" | "running" | "completed" | "failed" | "skipped";
|
|
30
30
|
export type TaskRunSkipReason = "missed" | "overlap" | "rate_limited" | "queue_paused" | "removed" | "device_offline" | "creator_inactive" | "agent_gone" | "target_gone" | "conversation_gone" | "org_disabled"
|
|
31
|
+
/** The channel's extension is disabled in the org: the task stays active. */
|
|
32
|
+
| "plugin_disabled"
|
|
31
33
|
/** A group chat on a channel without threads (a group run needs its own thread). */
|
|
32
34
|
| "unsupported_target"
|
|
33
35
|
/** The task was deleted after the run was recorded. */
|
|
@@ -18,8 +18,23 @@ export { APPROVAL_DENY_REASON_MAX_CHARS } from "../conversations/events.js";
|
|
|
18
18
|
export declare const APPROVALS_LIST_MAX = 100;
|
|
19
19
|
export type ApprovalStatus = "pending" | "approved" | "denied" | "expired" | "cancelled" | "skipped";
|
|
20
20
|
export type ApprovalScope = "once" | "session" | "always";
|
|
21
|
-
/**
|
|
22
|
-
|
|
21
|
+
/**
|
|
22
|
+
* What an approval asks: a tool call, the device owner about refused network hosts, or the actor
|
|
23
|
+
* about a git push the gateway held.
|
|
24
|
+
*/
|
|
25
|
+
export type ApprovalKind = "tool" | "network" | "git";
|
|
26
|
+
/**
|
|
27
|
+
* The formatted `tool_result` of a command an ask kept (≤ 16 KB; larger output already archived),
|
|
28
|
+
* and the display-only fields the pipeline writes with it when the ask settles.
|
|
29
|
+
*/
|
|
30
|
+
export interface KeptToolResult {
|
|
31
|
+
content: string;
|
|
32
|
+
isError: boolean;
|
|
33
|
+
outputId?: string;
|
|
34
|
+
contentTypes?: string[];
|
|
35
|
+
display?: ToolDisplay;
|
|
36
|
+
view?: ToolView;
|
|
37
|
+
}
|
|
23
38
|
/**
|
|
24
39
|
* A network ask's `detail` (network ask-to-allow spec §6.1, P-D2): the device, the refused hosts,
|
|
25
40
|
* the command and its kept `tool_result` (written with a note when the ask settles; the command is
|
|
@@ -33,18 +48,8 @@ export interface NetworkAskDetail {
|
|
|
33
48
|
}[];
|
|
34
49
|
command: string;
|
|
35
50
|
description: string | null;
|
|
36
|
-
/**
|
|
37
|
-
|
|
38
|
-
* display-only fields the pipeline writes with it when the ask settles.
|
|
39
|
-
*/
|
|
40
|
-
result: {
|
|
41
|
-
content: string;
|
|
42
|
-
isError: boolean;
|
|
43
|
-
outputId?: string;
|
|
44
|
-
contentTypes?: string[];
|
|
45
|
-
display?: ToolDisplay;
|
|
46
|
-
view?: ToolView;
|
|
47
|
-
};
|
|
51
|
+
/** The formatted `tool_result` of the command and its display-only fields. */
|
|
52
|
+
result: KeptToolResult;
|
|
48
53
|
/** The hosts the decision allowed (every approved decision writes them; none: nothing). */
|
|
49
54
|
grantedHosts?: string[];
|
|
50
55
|
/**
|
|
@@ -74,11 +79,32 @@ export interface NetworkAskAttempt {
|
|
|
74
79
|
}
|
|
75
80
|
/** A network ask's detail as the API shows it: without the kept command result. */
|
|
76
81
|
export type NetworkAskView = Omit<NetworkAskDetail, "result">;
|
|
82
|
+
/**
|
|
83
|
+
* A git push ask's `detail` (sandbox git credentials spec §7): the host, the repository
|
|
84
|
+
* (`<owner>/<repo>`, normalized) and the refs of the push the gateway held, the command that ran
|
|
85
|
+
* it and its device, the kept `tool_result` (written with a note when the ask settles; the push is
|
|
86
|
+
* never run again by the kernel), and once approved what took effect. The connector whose
|
|
87
|
+
* credential the push used is the approval's `connectorId`.
|
|
88
|
+
*/
|
|
89
|
+
export interface GitAskDetail {
|
|
90
|
+
host: string;
|
|
91
|
+
repo: string;
|
|
92
|
+
refs: string[];
|
|
93
|
+
command?: string;
|
|
94
|
+
deviceId?: string;
|
|
95
|
+
result: KeptToolResult;
|
|
96
|
+
/** What took effect: a run grant (`once`) or the member's standing allow for the repo (`always`). */
|
|
97
|
+
outcome?: "once" | "always";
|
|
98
|
+
}
|
|
99
|
+
/** A git ask's detail as the API shows it: without the kept command result. */
|
|
100
|
+
export type GitAskView = Omit<GitAskDetail, "result">;
|
|
77
101
|
/**
|
|
78
102
|
* The model-visible note written after a network ask's kept result when its run is stopped before
|
|
79
103
|
* the device owner answered (spec §6.7).
|
|
80
104
|
*/
|
|
81
105
|
export declare const NETWORK_ASK_CANCELLED_NOTE = "[network] The run was stopped before the user answered; access stays blocked.";
|
|
106
|
+
/** The model-visible note after a git ask's kept result when its run is stopped before the answer. */
|
|
107
|
+
export declare const GIT_ASK_CANCELLED_NOTE = "[git] The run was stopped before the user answered; the push was not made.";
|
|
82
108
|
/** 一条审批记录。 */
|
|
83
109
|
export interface ApprovalRecord {
|
|
84
110
|
id: string;
|
|
@@ -90,8 +116,10 @@ export interface ApprovalRecord {
|
|
|
90
116
|
attempt: number;
|
|
91
117
|
/** `network`: a network ask (its tool key is `Bash`, its facts in {@link detail}). */
|
|
92
118
|
kind: ApprovalKind;
|
|
93
|
-
/** A network ask's hosts, command, kept result and outcome; null for
|
|
119
|
+
/** A network ask's hosts, command, kept result and outcome; null for any other kind. */
|
|
94
120
|
detail: NetworkAskDetail | null;
|
|
121
|
+
/** A git ask's host, repository, refs, kept result and outcome; null for any other kind. */
|
|
122
|
+
git: GitAskDetail | null;
|
|
95
123
|
toolKey: string;
|
|
96
124
|
specHash: string;
|
|
97
125
|
connectorId: string | null;
|
|
@@ -117,11 +145,12 @@ export interface ApprovalRecord {
|
|
|
117
145
|
expiresAt: string;
|
|
118
146
|
createdAt: string;
|
|
119
147
|
}
|
|
120
|
-
/** An approval as a route answers it: a network ask's detail without the kept command result. */
|
|
121
|
-
export interface ApprovalPublicRecord extends Omit<ApprovalRecord, "detail"> {
|
|
148
|
+
/** An approval as a route answers it: a network or git ask's detail without the kept command result. */
|
|
149
|
+
export interface ApprovalPublicRecord extends Omit<ApprovalRecord, "detail" | "git"> {
|
|
122
150
|
detail: NetworkAskView | null;
|
|
151
|
+
git: GitAskView | null;
|
|
123
152
|
}
|
|
124
|
-
/** The record without
|
|
153
|
+
/** The record without an ask's kept command result (what routes and cards may show). */
|
|
125
154
|
export declare function publicRecord(r: ApprovalRecord): ApprovalPublicRecord;
|
|
126
155
|
/** 审批详情(列表与详情接口返回)。 */
|
|
127
156
|
export interface ApprovalView extends ApprovalPublicRecord {
|
|
@@ -210,6 +239,22 @@ export interface NetworkAskInput {
|
|
|
210
239
|
}
|
|
211
240
|
/** The tool key a network ask is recorded under (the command ran in `Bash`). */
|
|
212
241
|
export declare const NETWORK_ASK_TOOL_KEY = "Bash";
|
|
242
|
+
/** The tool key a git ask is recorded under (the push ran in a `Bash` command). */
|
|
243
|
+
export declare const GIT_ASK_TOOL_KEY = "Bash";
|
|
244
|
+
/** A new git push ask (sandbox git credentials spec §7), made by the tool pipeline. */
|
|
245
|
+
export interface GitAskInput {
|
|
246
|
+
orgId: string;
|
|
247
|
+
conversationId: string;
|
|
248
|
+
runId: string;
|
|
249
|
+
/** The call's step (written to `approval_requested`). */
|
|
250
|
+
step: number;
|
|
251
|
+
callId: string;
|
|
252
|
+
/** The actor whose credential the push used: the only person who may decide. */
|
|
253
|
+
requestedFor: string;
|
|
254
|
+
/** The connector whose credential the push used (its git source). */
|
|
255
|
+
connectorId: string;
|
|
256
|
+
detail: Omit<GitAskDetail, "outcome">;
|
|
257
|
+
}
|
|
213
258
|
/** 「以后都允许」授权(本人可撤销)。 */
|
|
214
259
|
export interface ToolGrantView {
|
|
215
260
|
agentId: string;
|
|
@@ -278,6 +323,17 @@ export declare class ApprovalsService {
|
|
|
278
323
|
*/
|
|
279
324
|
requestNetwork(input: NetworkAskInput): Promise<ApprovalRecord>;
|
|
280
325
|
private requestNetworkIn;
|
|
326
|
+
/**
|
|
327
|
+
* A git push ask (sandbox git credentials spec §7): a pending approval of kind `git` for the
|
|
328
|
+
* actor whose credential the push used, expiring like a tool approval, and its
|
|
329
|
+
* `approval_requested` (tool key `Bash`, the display-only `git` field), in one transaction. The
|
|
330
|
+
* scopes are `once` (a run grant) and, for a personal connector (the push used the actor's own
|
|
331
|
+
* connection), `always` (the actor's standing allow for the repository); an org connector's push
|
|
332
|
+
* acts as the org, so no member allow applies to it. Takes the attempt after the call's other
|
|
333
|
+
* approvals; one per call: a second request returns the first.
|
|
334
|
+
*/
|
|
335
|
+
requestGit(input: GitAskInput): Promise<ApprovalRecord>;
|
|
336
|
+
private requestGitIn;
|
|
281
337
|
/** 当前用户能处理的审批(新的在前,最多 {@link APPROVALS_LIST_MAX} 条);`status` 缺省为全部。 */
|
|
282
338
|
list(orgId: string, accountId: string, status?: ApprovalStatus): Promise<ApprovalView[]>;
|
|
283
339
|
/** 详情;当前用户不能处理的一律 `approval.not_found`(不泄露存在)。 */
|
|
@@ -302,6 +358,15 @@ export declare class ApprovalsService {
|
|
|
302
358
|
* (`late`) and answered with a 409 that says so.
|
|
303
359
|
*/
|
|
304
360
|
private decideNetwork;
|
|
361
|
+
/**
|
|
362
|
+
* A git push ask's decision (sandbox git credentials spec §7): only the asked actor
|
|
363
|
+
* (`requested_for`) decides, in a signed-in session (a personal access token is refused, as for
|
|
364
|
+
* network asks); `once` is a run grant (the row itself), `always` also writes the actor's
|
|
365
|
+
* standing allow for the repository on that host (`connector_tool_account_policies`,
|
|
366
|
+
* `git_push:<host>/<owner>/<repo>`) in the decision's transaction. The run resumes after the
|
|
367
|
+
* commit.
|
|
368
|
+
*/
|
|
369
|
+
private decideGit;
|
|
305
370
|
/**
|
|
306
371
|
* 「这台设备一直允许」 (transactional outbox spec §7): the intent of the device change (naming the
|
|
307
372
|
* ask) is recorded, the `policy` op sent (no transaction open), then {@link settleNetworkOp}
|
|
@@ -390,6 +455,19 @@ export declare class ApprovalsService {
|
|
|
390
455
|
* decided or one asked of someone else. In the decision's transaction.
|
|
391
456
|
*/
|
|
392
457
|
private keepTrialNetworkGrant;
|
|
458
|
+
/**
|
|
459
|
+
* The actor's standing allow for pushes to `repo` through the connector (sandbox git
|
|
460
|
+
* credentials spec §7, 「一直允许」): a `connector_tool_account_policies` row named
|
|
461
|
+
* `git_push:<host>/<owner>/<repo>` with policy `allow`, in the decision's transaction.
|
|
462
|
+
*/
|
|
463
|
+
private allowRepoIn;
|
|
464
|
+
/**
|
|
465
|
+
* A trial run of a scheduled task (sandbox git credentials spec §7): a push its creator allowed
|
|
466
|
+
* for this run (「这次允许」) becomes the task's `git:push:<owner>/<repo>` grant, when
|
|
467
|
+
* `gitGrantRefusal` allows it (the org does not forbid it). Never for an ask another account
|
|
468
|
+
* decided or one asked of someone else. In the decision's transaction.
|
|
469
|
+
*/
|
|
470
|
+
private keepTrialGitGrant;
|
|
393
471
|
/**
|
|
394
472
|
* 详情,不做处理人校验(内核内部用:渠道出站投递组装 IM 审批卡片);不存在返回 null。
|
|
395
473
|
* 不得直接回给请求方——HTTP 接口用 {@link get}。
|
|
@@ -399,6 +477,8 @@ export declare class ApprovalsService {
|
|
|
399
477
|
forCall(runId: string, callId: string): Promise<ApprovalRecord | null>;
|
|
400
478
|
/** The network ask of a tool call (at most one per call); null when it has none. */
|
|
401
479
|
networkForCall(runId: string, callId: string): Promise<ApprovalRecord | null>;
|
|
480
|
+
/** The git push ask of a tool call (at most one per call); null when it has none. */
|
|
481
|
+
gitForCall(runId: string, callId: string): Promise<ApprovalRecord | null>;
|
|
402
482
|
/**
|
|
403
483
|
* 超时(等待机制的超时任务调用):仍 pending 且已到期 → 置 expired、写 `approval_decided{expired}`(处理人为 null)。
|
|
404
484
|
* 与人工决定都锁同一行,恰好一个生效。返回 `expired`(本次生效)/ `not_due`(尚未到期)/
|
|
@@ -437,7 +517,8 @@ export declare class ApprovalsService {
|
|
|
437
517
|
/**
|
|
438
518
|
* In the caller's transaction (`mandatory`; it wrote `authorAccountId`'s message in
|
|
439
519
|
* `conversationId` and holds that conversation's row lock): the message skips the pending
|
|
440
|
-
* network asks it closes (network ask-to-allow spec §6.7
|
|
520
|
+
* network and git asks it closes (network ask-to-allow spec §6.7; a git push ask follows the
|
|
521
|
+
* same flow, sandbox git credentials spec §7), as it skips questions: the asks of
|
|
441
522
|
* active runs `authorAccountId` started, in the conversation and in its sub-agents'
|
|
442
523
|
* conversations at any depth (their asks are shown in the root). Each becomes `skipped` with
|
|
443
524
|
* `approval_decided{skipped}` by the author; access stays blocked. Returns the skipped records and
|