@agent-compose/sdk 0.8.4 → 0.8.6
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 +213 -189
- package/dist/agent/agent-context.d.ts +9 -1
- package/dist/agent/agent-loop.d.ts +14 -6
- package/dist/agent/perf-sampler.d.ts +27 -2
- package/dist/agent/run-agent.d.ts +1 -1
- package/dist/client.d.ts +250 -59
- package/dist/directives.d.ts +14 -0
- package/dist/display.d.ts +7 -0
- package/dist/errors.d.ts +1 -1
- package/dist/generated/agentc-commands.d.ts +34 -0
- package/dist/index.d.ts +13 -11
- package/dist/index.js +1692 -194
- package/dist/request-context/request-context.d.ts +1 -1
- package/dist/runtimes/_cli-agent.d.ts +278 -58
- package/dist/runtimes/claude-code.d.ts +90 -1
- package/dist/runtimes/claude.d.ts +1 -1
- package/dist/runtimes/codex.d.ts +94 -6
- package/dist/runtimes/codex.mid-turn-hook.test.d.ts +10 -0
- package/dist/runtimes/openai-desktop.d.ts +50 -0
- package/dist/runtimes/openai-desktop.js +1689 -211
- package/dist/runtimes/openai-desktop.test.d.ts +20 -0
- package/dist/runtimes/opencode.d.ts +48 -11
- package/dist/runtimes/opencode.test.d.ts +14 -0
- package/dist/runtimes/tool-pulse.test.d.ts +17 -0
- package/dist/sandbox/baked-clis.d.ts +75 -0
- package/dist/sandbox/devbox.d.ts +5 -5
- package/dist/sandbox/exec-stream.d.ts +1 -2
- package/dist/sandbox/network-policy.d.ts +23 -5
- package/dist/sandbox/registry.d.ts +12 -0
- package/dist/sandbox/sizes.d.ts +11 -5
- package/dist/sandbox.d.ts +5 -3
- package/dist/step-invocation/protocol.d.ts +3 -4
- package/dist/step-invocation/server.d.ts +2 -2
- package/dist/step-invocation/types.d.ts +2 -2
- package/dist/types/api-conversations.d.ts +513 -27
- package/dist/types/api-factory.d.ts +183 -3
- package/dist/types/api-projects.d.ts +480 -0
- package/dist/types/api-runs.d.ts +8 -0
- package/dist/types/api-scopes.d.ts +32 -3
- package/dist/types/conversation-stream.d.ts +27 -1
- package/dist/types/execution-context.d.ts +1 -1
- package/dist/types/protocol.d.ts +182 -2
- package/dist/types/runtime.d.ts +80 -2
- package/dist/types/workflow-metadata.d.ts +2 -4
- package/dist/types/workflow-plan.d.ts +1 -3
- package/dist/utils/bundler.d.ts +23 -0
- package/dist/workflow-steps/observability.d.ts +2 -3
- package/dist/workflow-steps/runner.d.ts +5 -8
- package/dist/workflow-steps/types.d.ts +8 -10
- package/dist/workflow-steps/workflow.d.ts +2 -1
- package/dist/workflows/engine.d.ts +3 -5
- package/dist/workflows/invoke-child.d.ts +2 -2
- package/package.json +2 -2
- package/src/agent/agent-context.ts +193 -116
- package/src/agent/agent-loop.ts +16 -9
- package/src/agent/desktop-open.ts +13 -1
- package/src/agent/perf-sampler.ts +54 -3
- package/src/agent/run-agent.ts +1 -1
- package/src/client.ts +418 -80
- package/src/directives.ts +21 -1
- package/src/display.ts +12 -0
- package/src/errors.ts +1 -0
- package/src/generated/agentc-commands.ts +571 -0
- package/src/index.ts +65 -18
- package/src/pause/pause-core.ts +2 -1
- package/src/request-context/request-context.ts +1 -1
- package/src/runtimes/_cli-agent.ts +607 -132
- package/src/runtimes/claude-code.ts +427 -20
- package/src/runtimes/claude.ts +1 -1
- package/src/runtimes/codex.ts +188 -19
- package/src/runtimes/openai-desktop.ts +82 -19
- package/src/runtimes/opencode.ts +195 -26
- package/src/sandbox/baked-clis.ts +86 -0
- package/src/sandbox/devbox.ts +5 -5
- package/src/sandbox/exec-stream.ts +1 -2
- package/src/sandbox/network-policy.ts +51 -7
- package/src/sandbox/providers/e2b.ts +63 -19
- package/src/sandbox/providers/vercel.ts +6 -6
- package/src/sandbox/registry.ts +19 -1
- package/src/sandbox/sizes.ts +11 -5
- package/src/sandbox.ts +9 -2
- package/src/step-invocation/invoker.ts +2 -6
- package/src/step-invocation/protocol.ts +3 -4
- package/src/step-invocation/server.ts +2 -2
- package/src/types/api-conversations.ts +424 -29
- package/src/types/api-factory.ts +189 -3
- package/src/types/api-projects.ts +443 -0
- package/src/types/api-runs.ts +5 -0
- package/src/types/api-scopes.ts +32 -3
- package/src/types/conversation-stream.ts +29 -1
- package/src/types/execution-context.ts +1 -1
- package/src/types/protocol.ts +180 -2
- package/src/types/runtime.ts +71 -2
- package/src/types/sandbox-environment.ts +1 -2
- package/src/types/workflow-metadata.ts +2 -4
- package/src/types/workflow-plan.ts +1 -3
- package/src/utils/bundler.ts +88 -19
- package/src/workflow-steps/observability.ts +2 -3
- package/src/workflow-steps/runner.ts +5 -8
- package/src/workflow-steps/types.ts +8 -10
- package/src/workflow-steps/workflow.ts +2 -1
- package/src/workflows/engine.ts +3 -5
- package/src/workflows/invoke-child.ts +2 -2
- package/dist/pause/__tests__/errors.test.d.ts +0 -1
- package/dist/pause/__tests__/wrappers.test.d.ts +0 -1
- package/dist/step-invocation/__tests__/protocol.test.d.ts +0 -1
package/src/client.ts
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import type { ConversationRow, CreateChatInput, ChannelIvyState, DriveSharesView, IvyConnectionsView, ListingPage } from "./types/api-conversations.js";
|
|
1
2
|
/**
|
|
2
3
|
* AgentComposeClient — HTTP client for the agent-compose server API.
|
|
3
4
|
*
|
|
@@ -32,11 +33,13 @@ import type {
|
|
|
32
33
|
ConversationsPage, SessionsPage, ConversationDetail, ConversationThread,
|
|
33
34
|
CreateCloudSessionInput, CloudSessionCreated,
|
|
34
35
|
SessionPreview, PreviewOpened, OpenPreviewInput, SessionForked, BackgroundWorkHeld,
|
|
35
|
-
|
|
36
|
-
|
|
36
|
+
BackgroundWorkChildDecl, BackgroundWorkStatus, MachineUpsizeOutcome,
|
|
37
|
+
CreateSessionWaitInput, SessionWait, SessionWaitCreated, SessionWaitList,
|
|
38
|
+
SessionChangeSet, SessionFilePlane, SessionMergeGated, SessionMergeReport, SessionDiscardReport,
|
|
39
|
+
SessionChangePreflight, SessionRebaseReport,
|
|
37
40
|
ReviewSuggestionInput, ReviewNotesPublished, ReviewGitCredential,
|
|
38
41
|
SendConversationMessageInput, SendConversationMessageResult,
|
|
39
|
-
ChannelSessionRow, ChannelSessionsResponse,
|
|
42
|
+
ChannelSessionRow, ChannelSessionsResponse,
|
|
40
43
|
SessionDirectMessageSent, BranchClaimGranted, BranchClaimsReleased, BranchClaimState,
|
|
41
44
|
ConversationPresenceSnapshot, StreamConversationOptions, AgentListRow,
|
|
42
45
|
SessionPerfHistoryPage,
|
|
@@ -46,20 +49,21 @@ import type {
|
|
|
46
49
|
SetScopeGrantsInput, SetTemplateScopeInput,
|
|
47
50
|
} from "./types/api-scopes.js";
|
|
48
51
|
import type {
|
|
49
|
-
Project, ProjectsPage, ProjectRole, ProjectMember,
|
|
50
|
-
ProjectObjectsPage, ProjectAddPreview,
|
|
51
|
-
AddProjectObjectInput, AddProjectObjectResult, RefreshProjectObjectResult,
|
|
52
|
+
Project, ProjectUpdate, ProjectsPage, ProjectRole, ProjectMember,
|
|
53
|
+
ProjectObject, ProjectObjectsPage, ProjectObjectCounts, ProjectAddPreview,
|
|
54
|
+
AddProjectObjectInput, AddProjectObjectResult, RefreshProjectObjectResult, ProjectStatus, ThreadStatus, MeStatus,
|
|
52
55
|
} from "./types/api-projects.js";
|
|
53
56
|
import type {
|
|
54
57
|
RegisterResult, RegisterWorkflowInput, TemplateRow, TemplateDetail, ListTemplatesOptions,
|
|
55
58
|
SearchFactoryFilesOptions, FactoryFileSearchResult, FactoryFileWriteResult,
|
|
56
|
-
FactoryFileListRow, ListFactoryFilesOptions, FactoryFileListPage,
|
|
59
|
+
FactoryFileListRow, ListFactoryFilesOptions, FactoryFileListPage, FactoryFileConflict, FactoryFileConflictList, ProjectSecretMeta, ProjectSecretList,
|
|
57
60
|
FactoryRow, CreateFactoryInput, UpdateFactoryInput, FactoryPerfSummary,
|
|
58
61
|
ScheduleRow, CreateScheduleInput,
|
|
59
|
-
SecretOptions, SetSecretResult, SecretListEntry, SessionSecretEntry, SessionSecretInput, SessionSecretRequestCreated, SessionSecretRequestStatus,
|
|
62
|
+
SecretOptions, SetSecretResult, SecretListEntry, SessionSecretEntry, SessionSecretInput, SessionSecretRequestCreated, SessionSecretRequestStatus, SessionSecretRequestSummary, VaultRequestKind, VaultKeyShape, VaultCatalogEntry, RequestedVaultEntry, VaultCardHint,
|
|
60
63
|
CreateApiKeyInput, ApiKey, ApiKeyCreated, ListApiKeysOptions, ApiKeyPage, UsageResponse,
|
|
61
|
-
DriveRepoLink, CreateDriveRepoLinkInput,
|
|
64
|
+
DriveRepoLink, CreateDriveRepoLinkInput, CreateNativeRepoInput, CreateNativeRepoResult,
|
|
62
65
|
DriveMountSession, CreateDriveMountSessionInput,
|
|
66
|
+
ConnectorGrantSummary,
|
|
63
67
|
} from "./types/api-factory.js";
|
|
64
68
|
import type {
|
|
65
69
|
ComplianceSession, RequestComplianceSessionInput, ListComplianceSessionsOptions,
|
|
@@ -85,18 +89,25 @@ export type {
|
|
|
85
89
|
} from "./types/api-runs.js";
|
|
86
90
|
export type {
|
|
87
91
|
TeamMember, Mention, CreateMentionsInput,
|
|
88
|
-
|
|
92
|
+
CreateChatInput, ChannelIvyState, IvyConnection, HiddenIvyConnection, IvyConnectionsView, IvyConnectionScope, ListingPage,
|
|
93
|
+
DriveShareItem, DriveShare, HiddenDriveShare, DriveSharesView,
|
|
94
|
+
WorkspaceConnection, WorkspaceConnectionAudienceEntry, WorkspaceConnectionsScopeView,
|
|
95
|
+
ConversationMessagePart, ConversationRow, ConversationProject, ConversationMessageRow,
|
|
89
96
|
ConversationsPage, SessionsPage, ConversationDetail,
|
|
90
97
|
CreateCloudSessionInput, CloudSessionCreated, ConversationThread,
|
|
98
|
+
ConversationUnreadSummary, ConversationUnreadThreads, ConversationReadInput, ConversationReadResult,
|
|
91
99
|
SessionPreview, PreviewOpened, OpenPreviewInput, SessionForked, BackgroundWorkHeld,
|
|
100
|
+
BackgroundWorkChildDecl, BackgroundWorkStatus, MachineUpsizeOutcome,
|
|
101
|
+
SessionWaitKind, SessionWaitState, CreateSessionWaitInput, SessionWait, SessionWaitCheck, SessionWaitCheckResult, SessionWaitCheckReview, SessionWaitCreated, SessionWaitList,
|
|
92
102
|
SessionFileChange, SessionChangeSet, SessionChangeStats, SessionDiffReviewBound, ReviewSuggestion,
|
|
103
|
+
SessionFileHold, SessionFilePlane,
|
|
93
104
|
ReviewSuggestionInput, ReviewNotesPublished, ReviewGitCredential, SessionReviewDocument,
|
|
94
105
|
ReviewSuggestionDecision, ReviewSuggestionDecisions,
|
|
95
106
|
SessionMergeReportDetail, SessionMergeReport, SessionMergeGated, SessionDiscardReport,
|
|
96
|
-
SessionPreflightFileRow, SessionChangePreflight, SessionRebaseReport,
|
|
107
|
+
SessionPreflightFileRow, SessionChangePreflight, SessionRebaseReport,
|
|
97
108
|
ConversationPageContext, SendConversationMessageInput, ConversationTurnState,
|
|
98
109
|
SendConversationMessageResult, UnnotifiedMention, ConversationPresenceSnapshot, AgentListRow, StreamConversationOptions,
|
|
99
|
-
ChannelSessionStatus, ChannelSessionRow,
|
|
110
|
+
ChannelSessionStatus, ChannelSessionRow, ChannelWorkerFacts, ChannelSessionsResponse,
|
|
100
111
|
SessionDirectMessageSent, BranchClaimInfo, BranchClaimGranted, BranchClaimsReleased, BranchClaimState,
|
|
101
112
|
SessionPerfBucket, SessionPerfHistoryPage,
|
|
102
113
|
} from "./types/api-conversations.js";
|
|
@@ -106,24 +117,30 @@ export type {
|
|
|
106
117
|
RunContext, SetScopeGrantsInput, SetTemplateScopeInput,
|
|
107
118
|
} from "./types/api-scopes.js";
|
|
108
119
|
export type {
|
|
109
|
-
Project, ProjectsPage, ProjectRole, ProjectMember,
|
|
110
|
-
ProjectObject, ProjectObjectsPage, ProjectSkippedFile, ProjectPreviewFile,
|
|
120
|
+
Project, ProjectUpdate, ProjectsPage, ProjectRole, ProjectMember,
|
|
121
|
+
ProjectObject, ProjectObjectsPage, ProjectObjectCounts, ProjectSkippedFile, ProjectPreviewFile,
|
|
111
122
|
ProjectAddPreview, AddProjectObjectInput, AddProjectObjectResult,
|
|
112
123
|
RefreshProjectObjectResult,
|
|
124
|
+
ProjectStatus, ProjectStatusThread, ProjectStatusTask, ProjectStatusPerson, ProjectStatusWorker, ProjectStatusActivity,
|
|
125
|
+
ProjectStatusActivityKind, ProjectStatusWaitingOn, ProjectStatusWaitingCount, ProjectStatusCounts,
|
|
126
|
+
ThreadStatus, ThreadStatusWorker, ThreadStatusWorkerState, ThreadStatusWorkerEffort, ThreadStatusTodo, ThreadStatusDirector, ThreadStatusOutput, ThreadStatusEvent, ChatWork, ChatWorkThread,
|
|
127
|
+
ThreadStatusWaitingOn, ThreadStatusAssignee, ThreadStatusTodoActivity, ChatTodoPatch, ChatTodoComment,
|
|
128
|
+
MeStatus, MeStatusCounts,
|
|
113
129
|
} from "./types/api-projects.js";
|
|
114
130
|
export type {
|
|
115
131
|
RegisterResult, RegisteredRuntime, RuntimeSourceInput, TemplateSourceRef, RegisterWorkflowInput,
|
|
116
132
|
TemplateRow, TemplateDetail, ListTemplatesOptions,
|
|
117
133
|
FactoryFileSearchRow, FactoryFolderSearchRow, SearchFactoryFilesOptions, FactoryFileSearchResult, FactoryFileWriteResult,
|
|
118
|
-
FactoryFileListRow, ListFactoryFilesOptions, FactoryFileListPage,
|
|
134
|
+
FactoryFileListRow, ListFactoryFilesOptions, FactoryFileListPage, FactoryFileConflict, FactoryFileConflictList, ProjectSecretMeta, ProjectSecretList,
|
|
119
135
|
PublicFileLinkState,
|
|
120
136
|
FactoryRow, CreateFactoryInput, UpdateFactoryInput, FactoryPerfSummary,
|
|
121
137
|
ScheduleRow, CreateScheduleInput,
|
|
122
|
-
SecretOptions, SetSecretResult, SecretListEntry, SessionSecretEntry, SessionSecretInput, SessionSecretRequestCreated, SessionSecretRequestStatus,
|
|
138
|
+
SecretOptions, SetSecretResult, SecretListEntry, SessionSecretEntry, SessionSecretInput, SessionSecretRequestCreated, SessionSecretRequestStatus, SessionSecretRequestSummary, VaultRequestKind, VaultKeyShape, VaultCatalogEntry, RequestedVaultEntry, VaultCardHint,
|
|
123
139
|
CreateApiKeyInput, ApiKey, ApiKeyCreated, ListApiKeysOptions, ApiKeyPage,
|
|
124
140
|
UsageRollupRow, UsageResponse,
|
|
125
|
-
DriveRepoLink, CreateDriveRepoLinkInput,
|
|
141
|
+
DriveRepoLink, CreateDriveRepoLinkInput, CreateNativeRepoInput, CreateNativeRepoResult,
|
|
126
142
|
DriveMountSession, CreateDriveMountSessionInput,
|
|
143
|
+
ConnectorGrantSummary,
|
|
127
144
|
} from "./types/api-factory.js";
|
|
128
145
|
export type {
|
|
129
146
|
ComplianceScopeKind, ComplianceStatus, ComplianceSession, ComplianceAccess,
|
|
@@ -151,6 +168,16 @@ function detectAmbientParentRunId(): string | null {
|
|
|
151
168
|
* URL-encoded as defense-in-depth: today's server-side patterns
|
|
152
169
|
* (`^[a-z][a-z0-9-]*$`) can't produce reserved characters, but a future
|
|
153
170
|
* relaxation would otherwise quietly become an injection vector. */
|
|
171
|
+
/** The query string of one page of a scope listing (`cursor`: the previous
|
|
172
|
+
* page's `nextCursor`; `limit`: 1..200). Empty for the first page at the
|
|
173
|
+
* server's size. */
|
|
174
|
+
function listingPageQuery(page: ListingPage = {}): string {
|
|
175
|
+
const q = new URLSearchParams();
|
|
176
|
+
if (page.cursor) q.set("cursor", page.cursor);
|
|
177
|
+
if (page.limit !== undefined) q.set("limit", String(page.limit));
|
|
178
|
+
return q.toString() ? `?${q}` : "";
|
|
179
|
+
}
|
|
180
|
+
|
|
154
181
|
function templatePath(factorySlug: string, ...rest: string[]): string {
|
|
155
182
|
const tail = rest.length > 0
|
|
156
183
|
? "/" + rest.map(encodeURIComponent).join("/")
|
|
@@ -770,6 +797,55 @@ export class AgentComposeClient {
|
|
|
770
797
|
};
|
|
771
798
|
}
|
|
772
799
|
|
|
800
|
+
/** Bounded, cursor-paginated conflicts. A session filter is applied in the database. */
|
|
801
|
+
/** Project secrets (the group tier) — names + metadata, project members only. */
|
|
802
|
+
listProjectSecrets(projectId: string): Promise<ProjectSecretList> {
|
|
803
|
+
return this.fetch(`/api/v1/projects/${encodeURIComponent(projectId)}/secrets`);
|
|
804
|
+
}
|
|
805
|
+
|
|
806
|
+
/** Upsert a project secret. Human credential required (a session toolbelt
|
|
807
|
+
* key is refused). Values are write-only — never echoed. */
|
|
808
|
+
upsertProjectSecret(projectId: string, secret: {
|
|
809
|
+
key: string; value: string;
|
|
810
|
+
delivery?: "injected" | "brokered"; brokerHost?: string; brokerHeaderName?: string; brokerHeaderScheme?: string;
|
|
811
|
+
}): Promise<{ key: string; delivery: "injected" | "brokered" }> {
|
|
812
|
+
return this.fetch(`/api/v1/projects/${encodeURIComponent(projectId)}/secrets`, {
|
|
813
|
+
method: "POST", body: JSON.stringify(secret),
|
|
814
|
+
});
|
|
815
|
+
}
|
|
816
|
+
|
|
817
|
+
deleteProjectSecret(projectId: string, key: string): Promise<void> {
|
|
818
|
+
return this.fetch(`/api/v1/projects/${encodeURIComponent(projectId)}/secrets/${encodeURIComponent(key)}`, { method: "DELETE" });
|
|
819
|
+
}
|
|
820
|
+
|
|
821
|
+
listFactoryFileConflicts(factorySlug: string, opts: { limit?: number; cursor?: string; conversationId?: string } = {}): Promise<FactoryFileConflictList> {
|
|
822
|
+
const q = new URLSearchParams();
|
|
823
|
+
if (opts.limit !== undefined) q.set("limit", String(opts.limit));
|
|
824
|
+
if (opts.cursor) q.set("cursor", opts.cursor);
|
|
825
|
+
if (opts.conversationId) q.set("conversationId", opts.conversationId);
|
|
826
|
+
return this.fetch(`/api/v1/factories/${encodeURIComponent(factorySlug)}/files/conflicts?${q}`);
|
|
827
|
+
}
|
|
828
|
+
|
|
829
|
+
async getFactoryFileConflictContent(factorySlug: string, id: string): Promise<Uint8Array> {
|
|
830
|
+
const bytes = await this.fetch<ArrayBuffer, "arrayBuffer">(
|
|
831
|
+
`/api/v1/factories/${encodeURIComponent(factorySlug)}/files/conflicts/${encodeURIComponent(id)}/content`,
|
|
832
|
+
{ responseType: "arrayBuffer" },
|
|
833
|
+
);
|
|
834
|
+
return new Uint8Array(bytes);
|
|
835
|
+
}
|
|
836
|
+
|
|
837
|
+
/** Records a decision about the exact inspected versions. Stale arms refuse. */
|
|
838
|
+
resolveFactoryFileConflict(factorySlug: string, id: string, decision: {
|
|
839
|
+
status: "resolved" | "dismissed";
|
|
840
|
+
settle: "branch" | "main";
|
|
841
|
+
expectedOursHash: string | null;
|
|
842
|
+
expectedTheirsHash: string | null;
|
|
843
|
+
}): Promise<FactoryFileConflict & { settled: "branch" | "main" | "row" }> {
|
|
844
|
+
return this.fetch(`/api/v1/factories/${encodeURIComponent(factorySlug)}/files/conflicts/${encodeURIComponent(id)}/resolve`, {
|
|
845
|
+
method: "POST", body: JSON.stringify(decision),
|
|
846
|
+
});
|
|
847
|
+
}
|
|
848
|
+
|
|
773
849
|
/** Read one file's current content (or a specific revision) as RAW BYTES —
|
|
774
850
|
* byte-exact for any content type. This is the wire truth; `getFactoryFile`
|
|
775
851
|
* is a UTF-8 decode over it. Binaries (images, archives) MUST come through
|
|
@@ -812,7 +888,7 @@ export class AgentComposeClient {
|
|
|
812
888
|
// ── User drive mounts ──────────────────────────────────────────────────────
|
|
813
889
|
// `agentc files mount` on a human's own machine: the server forks a user
|
|
814
890
|
// branch, backs it with a mount session (the review surface), and mints a
|
|
815
|
-
// user-principal gateway token.
|
|
891
|
+
// user-principal gateway token. Own-device credentials only (sign-in
|
|
816
892
|
// cookie or a device-flow bridge key) — sandbox session keys are refused.
|
|
817
893
|
|
|
818
894
|
/** Create a local drive mount (or re-mint an existing one's token by
|
|
@@ -860,6 +936,27 @@ export class AgentComposeClient {
|
|
|
860
936
|
// access. Key callers see what their sender scope allows; the server is the
|
|
861
937
|
// sole authority — these are thin typed wrappers.
|
|
862
938
|
|
|
939
|
+
/** Create a shared chat, including its own Ivy by default. */
|
|
940
|
+
createChat(input: CreateChatInput): Promise<ConversationRow> {
|
|
941
|
+
return this.fetch("/api/v1/conversations", { method: "POST", body: JSON.stringify(input), headers: { "content-type": "application/json" } });
|
|
942
|
+
}
|
|
943
|
+
getChannelIvy(id: string): Promise<ChannelIvyState> {
|
|
944
|
+
return this.fetch(`/api/v1/conversations/${encodeURIComponent(id)}/ivy`);
|
|
945
|
+
}
|
|
946
|
+
/** A project's GitHub grants: its own, and the workspace's it inherits,
|
|
947
|
+
* one page at a time (pass the previous page's `nextCursor`). A
|
|
948
|
+
* project's access is its members' (and the workspace admins'): a
|
|
949
|
+
* member of the workspace who can see a public project without being in
|
|
950
|
+
* it gets a 403 `project_member_required`. */
|
|
951
|
+
listProjectIvyConnections(id: string, page?: ListingPage): Promise<IvyConnectionsView> {
|
|
952
|
+
return this.fetch(`/api/v1/projects/${encodeURIComponent(id)}/ivy-connections${listingPageQuery(page)}`);
|
|
953
|
+
}
|
|
954
|
+
/** A project's Drive shares: its own, and the workspace's it inherits,
|
|
955
|
+
* one page at a time. Members only, as listProjectIvyConnections. */
|
|
956
|
+
listProjectDriveShares(id: string, page?: ListingPage): Promise<DriveSharesView> {
|
|
957
|
+
return this.fetch(`/api/v1/projects/${encodeURIComponent(id)}/drive-shares${listingPageQuery(page)}`);
|
|
958
|
+
}
|
|
959
|
+
|
|
863
960
|
/** List conversations the caller can access, newest-activity first.
|
|
864
961
|
* Cursor-paginated: pass the previous page's `next_cursor`. */
|
|
865
962
|
listConversations(opts?: { cursor?: string }): Promise<ConversationsPage> {
|
|
@@ -987,25 +1084,6 @@ export class AgentComposeClient {
|
|
|
987
1084
|
);
|
|
988
1085
|
}
|
|
989
1086
|
|
|
990
|
-
/** Post one message into a channel AS the calling session (ADR-0057 Seam
|
|
991
|
-
* 4) — progress, results, questions, attributed to the session (title +
|
|
992
|
-
* runtime mark). Session toolbelt credential ONLY (the calling session
|
|
993
|
-
* resolves from the key server-side — 403 `session_credential_required`
|
|
994
|
-
* otherwise); the session must be attached (409 `not_attached`). By
|
|
995
|
-
* default the post lands in the thread of the message that last
|
|
996
|
-
* addressed the session from that channel (the room when none);
|
|
997
|
-
* `threadRootId` overrides it — must be a root message in the channel
|
|
998
|
-
* (400 `invalid_thread_root`). The post never triggers any turn. */
|
|
999
|
-
postSessionChannelMessage(
|
|
1000
|
-
channelId: string,
|
|
1001
|
-
input: { text: string; threadRootId?: string },
|
|
1002
|
-
): Promise<SessionChannelMessagePosted> {
|
|
1003
|
-
return this.fetch<SessionChannelMessagePosted>(
|
|
1004
|
-
`/api/v1/conversations/${encodeURIComponent(channelId)}/session-messages`,
|
|
1005
|
-
{ method: "POST", body: { text: input.text, ...(input.threadRootId ? { threadRootId: input.threadRootId } : {}) } },
|
|
1006
|
-
);
|
|
1007
|
-
}
|
|
1008
|
-
|
|
1009
1087
|
/** Message ANOTHER session's conversation AS the calling session
|
|
1010
1088
|
* (`agentc session message @alias`). Session toolbelt credential ONLY —
|
|
1011
1089
|
* the sender resolves from the key. `target` is an @alias (team-scoped)
|
|
@@ -1095,19 +1173,88 @@ export class AgentComposeClient {
|
|
|
1095
1173
|
* background-work busy lease: while it is live, the between-turns
|
|
1096
1174
|
* park/suspend leaves the session's VM running so work the turn left
|
|
1097
1175
|
* behind keeps executing. The lease lapses on its own — re-hold to
|
|
1098
|
-
* extend past `minutes` (server-capped).
|
|
1099
|
-
|
|
1176
|
+
* extend past `minutes` (server-capped). `children` descriptors
|
|
1177
|
+
* ({pid, journalPath, label}) register the DETACHED processes the hold
|
|
1178
|
+
* vouches for, so the platform can verify and reattach them after a
|
|
1179
|
+
* park (task #63). Write-tier. */
|
|
1180
|
+
holdBackgroundWork(
|
|
1181
|
+
conversationId: string,
|
|
1182
|
+
input?: { minutes?: number; children?: BackgroundWorkChildDecl[] },
|
|
1183
|
+
): Promise<BackgroundWorkHeld> {
|
|
1100
1184
|
return this.fetch<BackgroundWorkHeld>(
|
|
1101
1185
|
`/api/v1/conversations/${encodeURIComponent(conversationId)}/background-work`,
|
|
1102
|
-
{ method: "POST", body: {
|
|
1186
|
+
{ method: "POST", body: {
|
|
1187
|
+
...(input?.minutes !== undefined ? { minutes: input.minutes } : {}),
|
|
1188
|
+
...(input?.children !== undefined ? { children: input.children } : {}),
|
|
1189
|
+
} },
|
|
1190
|
+
);
|
|
1191
|
+
}
|
|
1192
|
+
|
|
1193
|
+
// ── Session waits (owner ruling 2026-09-23: no watch runs inside a session
|
|
1194
|
+
// sandbox). The session declares what it waits for and ends its turn; the
|
|
1195
|
+
// platform senses the arrival and wakes it. Own-session key posture. ─────
|
|
1196
|
+
|
|
1197
|
+
/** Declare one wait (`agentc wait`): `POST /sessions/:id/waits`. */
|
|
1198
|
+
createSessionWait(conversationId: string, input: CreateSessionWaitInput): Promise<SessionWaitCreated> {
|
|
1199
|
+
return this.fetch<SessionWaitCreated>(
|
|
1200
|
+
`/api/v1/sessions/${encodeURIComponent(conversationId)}/waits`,
|
|
1201
|
+
{ method: "POST", body: input },
|
|
1202
|
+
);
|
|
1203
|
+
}
|
|
1204
|
+
|
|
1205
|
+
/** This session's waits, newest first; open only unless `all`. */
|
|
1206
|
+
listSessionWaits(conversationId: string, opts: { all?: boolean } = {}): Promise<SessionWaitList> {
|
|
1207
|
+
const q = opts.all ? "?all=1" : "";
|
|
1208
|
+
return this.fetch<SessionWaitList>(`/api/v1/sessions/${encodeURIComponent(conversationId)}/waits${q}`);
|
|
1209
|
+
}
|
|
1210
|
+
|
|
1211
|
+
/** Cancel an open wait (`agentc wait cancel`): open -> cancelled. */
|
|
1212
|
+
cancelSessionWait(conversationId: string, waitId: string): Promise<SessionWait> {
|
|
1213
|
+
return this.fetch<SessionWait>(
|
|
1214
|
+
`/api/v1/sessions/${encodeURIComponent(conversationId)}/waits/${encodeURIComponent(waitId)}`,
|
|
1215
|
+
{ method: "DELETE" },
|
|
1216
|
+
);
|
|
1217
|
+
}
|
|
1218
|
+
|
|
1219
|
+
/** Request ONE machine size up for a cloud session (task #110 — the
|
|
1220
|
+
* auto-resize policy's agent door). The platform arbitrates: within the
|
|
1221
|
+
* team's daily cap the upsize is auto-granted (and executes the moment
|
|
1222
|
+
* no live turn / background work holds the machine — home essentials
|
|
1223
|
+
* carry over); past the cap it becomes an owner approval card.
|
|
1224
|
+
* Deliberately not `resize`: the in-sandbox toolbelt key may call THIS,
|
|
1225
|
+
* because the kill only ever happens under platform policy or human
|
|
1226
|
+
* approval. Refusals (memory ceiling, template-pinned, ended) arrive as
|
|
1227
|
+
* HTTP 409s carrying `code`. Write-tier. */
|
|
1228
|
+
requestMachineUpsize(
|
|
1229
|
+
conversationId: string, input?: { reason?: string },
|
|
1230
|
+
): Promise<MachineUpsizeOutcome> {
|
|
1231
|
+
return this.fetch<MachineUpsizeOutcome>(
|
|
1232
|
+
`/api/v1/conversations/${encodeURIComponent(conversationId)}/machine/request-upsize`,
|
|
1233
|
+
{ method: "POST", body: input?.reason ? { reason: input.reason } : {} },
|
|
1234
|
+
);
|
|
1235
|
+
}
|
|
1236
|
+
|
|
1237
|
+
/** The session's background-work status: the lease deadline, the declared
|
|
1238
|
+
* children, and the owed-report marker a mid-work park leaves behind.
|
|
1239
|
+
* Read-tier. */
|
|
1240
|
+
getBackgroundWork(conversationId: string): Promise<BackgroundWorkStatus> {
|
|
1241
|
+
return this.fetch<BackgroundWorkStatus>(
|
|
1242
|
+
`/api/v1/conversations/${encodeURIComponent(conversationId)}/background-work`,
|
|
1103
1243
|
);
|
|
1104
1244
|
}
|
|
1105
1245
|
|
|
1106
1246
|
/** Release the session's background-work lease (the work finished).
|
|
1107
|
-
* Idempotent — `released` is false when no lease was held.
|
|
1108
|
-
|
|
1247
|
+
* Idempotent — `released` is false when no lease was held. `pid` scopes
|
|
1248
|
+
* the release to ONE declared child (what a `--while-pid` holder passes
|
|
1249
|
+
* when its watched process dies): the child is pruned from the declared
|
|
1250
|
+
* registry, and the lease clears only when it was the last — a sibling's
|
|
1251
|
+
* death never erases the other holders' declarations. */
|
|
1252
|
+
async releaseBackgroundWork(
|
|
1253
|
+
conversationId: string, opts?: { pid?: number },
|
|
1254
|
+
): Promise<boolean> {
|
|
1255
|
+
const pidQuery = opts?.pid !== undefined ? `?pid=${encodeURIComponent(opts.pid)}` : "";
|
|
1109
1256
|
const body = await this.fetch<{ released: boolean }>(
|
|
1110
|
-
`/api/v1/conversations/${encodeURIComponent(conversationId)}/background-work`,
|
|
1257
|
+
`/api/v1/conversations/${encodeURIComponent(conversationId)}/background-work${pidQuery}`,
|
|
1111
1258
|
{ method: "DELETE" },
|
|
1112
1259
|
);
|
|
1113
1260
|
return body.released;
|
|
@@ -1168,17 +1315,30 @@ export class AgentComposeClient {
|
|
|
1168
1315
|
return new Uint8Array(buf);
|
|
1169
1316
|
}
|
|
1170
1317
|
|
|
1318
|
+
/** Where ONE path's current version lives for a session
|
|
1319
|
+
* (`GET /conversations/:id/changes/file`): `main` when the main drive
|
|
1320
|
+
* holds the session branch's version (landed, or never changed on the
|
|
1321
|
+
* branch), else `branch` with `why` naming what keeps it off main. The
|
|
1322
|
+
* answer a `file:<path>?session=<id>` link resolves when it is opened.
|
|
1323
|
+
* 404 = missing path or no access (uniform, no existence oracle). */
|
|
1324
|
+
getSessionFilePlane(conversationId: string, path: string): Promise<SessionFilePlane> {
|
|
1325
|
+
const q = new URLSearchParams({ path });
|
|
1326
|
+
return this.fetch<SessionFilePlane>(
|
|
1327
|
+
`/api/v1/conversations/${encodeURIComponent(conversationId)}/changes/file?${q}`,
|
|
1328
|
+
);
|
|
1329
|
+
}
|
|
1330
|
+
|
|
1171
1331
|
/** Publish a diff review's WHOLE document — prose notes plus structured
|
|
1172
1332
|
* suggestions, FULL REPLACE on every call (`POST
|
|
1173
1333
|
* /conversations/:id/review-notes`; `agentc review publish`). Callable
|
|
1174
|
-
* ONLY with the
|
|
1175
|
-
*
|
|
1176
|
-
*
|
|
1177
|
-
*
|
|
1334
|
+
* ONLY with the toolbelt credential of a review session spawned for this
|
|
1335
|
+
* diff, which replaces its own document — any other key (another
|
|
1336
|
+
* session, a human cookie, a plain API key) refuses 403.
|
|
1337
|
+
* `conversationId` is the REVIEWED session's conversation (in a review
|
|
1338
|
+
* sandbox: `AGENT_COMPOSE_REVIEW_OF_CONVERSATION_ID`).
|
|
1178
1339
|
*
|
|
1179
|
-
* Failures: 403 `session_credential_required` | `not_review_session
|
|
1180
|
-
* `
|
|
1181
|
-
* `suggestion_path_not_in_change_set` (naming the offenders); 409
|
|
1340
|
+
* Failures: 403 `session_credential_required` | `not_review_session`;
|
|
1341
|
+
* 400 `suggestion_path_not_in_change_set` (naming the offenders); 409
|
|
1182
1342
|
* `review_disabled`. */
|
|
1183
1343
|
publishReviewNotes(
|
|
1184
1344
|
conversationId: string,
|
|
@@ -1214,6 +1374,43 @@ export class AgentComposeClient {
|
|
|
1214
1374
|
);
|
|
1215
1375
|
}
|
|
1216
1376
|
|
|
1377
|
+
/** Mint a short-lived native-git credential for a linked repo's MIRROR
|
|
1378
|
+
* namespace (`POST /:slug/repo-links/:id/git-credential`, git-door
|
|
1379
|
+
* slice 4). mode "fetch" (default) reads the mirror — gated on link
|
|
1380
|
+
* visibility; mode "mirror" pushes real GitHub history through the
|
|
1381
|
+
* closure-verified door — gated on the repo_link WRITE capability.
|
|
1382
|
+
* 409 `git_remote_unavailable` when no git plane serves the factory. */
|
|
1383
|
+
getRepoLinkGitCredential(linkId: string, opts?: { mode?: "fetch" | "mirror" | "github" | "native"; factorySlug?: string }):
|
|
1384
|
+
Promise<{
|
|
1385
|
+
url: string; username: string; password: string; repoUrl: string;
|
|
1386
|
+
/** Absent in `github` mode (the credential targets github.com, not the platform git plane). */
|
|
1387
|
+
namespace?: string; expiresAt: string; mode: string;
|
|
1388
|
+
/** `github` mode only: the host the credential is for. */
|
|
1389
|
+
host?: string;
|
|
1390
|
+
/** `github` mode only: the token's ceiling — "write" (contents:write,
|
|
1391
|
+
* push-capable) for viewers with write capability on the link,
|
|
1392
|
+
* "read" (clone/fetch only) otherwise. */
|
|
1393
|
+
access?: "read" | "write";
|
|
1394
|
+
/** `github` mode only: the GRANTED permission map GitHub echoed at
|
|
1395
|
+
* mint (e.g. `{contents:"write", pulls:"write"}`). A capability
|
|
1396
|
+
* missing here (pulls, issues) means the App installation does not
|
|
1397
|
+
* carry it — the OWNER must widen the installation; retrying can
|
|
1398
|
+
* never help. */
|
|
1399
|
+
permissions?: Record<string, string>;
|
|
1400
|
+
/** `github` mode only: the INSTALLATION's recorded grant ledger
|
|
1401
|
+
* (`key:level` strings, probe-synced). A capability present here
|
|
1402
|
+
* but missing from `permissions` is a platform downscope; missing
|
|
1403
|
+
* from both layers, an App-installation gap only the owner can
|
|
1404
|
+
* widen. Empty = not yet recorded (reconnect or next probe). */
|
|
1405
|
+
installationScopes?: string[];
|
|
1406
|
+
}> {
|
|
1407
|
+
const slug = opts?.factorySlug ?? DEFAULT_FACTORY;
|
|
1408
|
+
return this.fetch(
|
|
1409
|
+
`/api/v1/factories/${encodeURIComponent(slug)}/repo-links/${encodeURIComponent(linkId)}/git-credential`,
|
|
1410
|
+
{ method: "POST", body: JSON.stringify({ mode: opts?.mode ?? "fetch" }), headers: { "content-type": "application/json" } },
|
|
1411
|
+
);
|
|
1412
|
+
}
|
|
1413
|
+
|
|
1217
1414
|
/** Approve the session's proposed changes: 3-way merge its branch into
|
|
1218
1415
|
* `main`, then continue the session on a fresh branch off post-merge
|
|
1219
1416
|
* `main`. Write-tier + human caller. Pass `opts.branch` (the branch you
|
|
@@ -1224,9 +1421,14 @@ export class AgentComposeClient {
|
|
|
1224
1421
|
* converged on) a kind='merge' approval routed to the session's
|
|
1225
1422
|
* approvers. Discriminate on `object`.
|
|
1226
1423
|
*
|
|
1227
|
-
* Failures: 403 `role_read_only` (read-only member)
|
|
1228
|
-
* session toolbelt
|
|
1229
|
-
*
|
|
1424
|
+
* Failures: 403 `role_read_only` (read-only member); 403 `not_own_branch`
|
|
1425
|
+
* (a session toolbelt key merges ONLY its own bound session's branch —
|
|
1426
|
+
* the agent self-merge door, owner ruling 2026-08-31); 403 `merge_gated`
|
|
1427
|
+
* (a gated session's self-merge — a designated approver merges from the
|
|
1428
|
+
* Changes panel instead, and no card is minted); 409 `turn_active` (a
|
|
1429
|
+
* turn is running — retry when idle; a session's OWN self-merge is
|
|
1430
|
+
* exempt) | `branch_changed` | `branch_claimed` (a teammate session
|
|
1431
|
+
* holds the branch claim — merge after it releases); 400
|
|
1230
1432
|
* `no_branch` (session predates branching); 502 `quiesce_failed`
|
|
1231
1433
|
* (nothing changed — safe to retry) | `merge_failed` (branch retained,
|
|
1232
1434
|
* named in the body) | `rebranch_failed` (merge landed; retry safe). */
|
|
@@ -1290,24 +1492,6 @@ export class AgentComposeClient {
|
|
|
1290
1492
|
);
|
|
1291
1493
|
}
|
|
1292
1494
|
|
|
1293
|
-
/** Arm/disarm the OPT-IN main-advance auto-rebase reflex for a session
|
|
1294
|
-
* (default OFF): when armed and the drive's main moves, the platform
|
|
1295
|
-
* preflights and — only on a provably clean fold (zero conflicts) —
|
|
1296
|
-
* rebases the session's branch from main headlessly, posting a quiet
|
|
1297
|
-
* receipt. Trade-off (why default OFF): the agent's view of files it
|
|
1298
|
-
* did not touch can change mid-task. Human, write-tier act.
|
|
1299
|
-
*
|
|
1300
|
-
* Failures: 409 `review_session_scratch` | `plane_unsupported`; 403
|
|
1301
|
-
* (needs a user-bound human caller with write access). */
|
|
1302
|
-
setSessionAutoRebase(
|
|
1303
|
-
conversationId: string, enabled: boolean,
|
|
1304
|
-
): Promise<SessionAutoRebaseState> {
|
|
1305
|
-
return this.fetch<SessionAutoRebaseState>(
|
|
1306
|
-
`/api/v1/conversations/${encodeURIComponent(conversationId)}/changes/autorebase`,
|
|
1307
|
-
{ method: "POST", body: { enabled } },
|
|
1308
|
-
);
|
|
1309
|
-
}
|
|
1310
|
-
|
|
1311
1495
|
// ── Conversation membership (ADR-0045) ────────────────────────────────────
|
|
1312
1496
|
// Channel rosters carry roles (`owner > write > read`). Inviting is a
|
|
1313
1497
|
// `write` action; removing and re-roling are `owner` (or team admin)
|
|
@@ -1336,8 +1520,10 @@ export class AgentComposeClient {
|
|
|
1336
1520
|
return body.members;
|
|
1337
1521
|
}
|
|
1338
1522
|
|
|
1339
|
-
/** Remove a member (conversation `owner` or team admin
|
|
1340
|
-
*
|
|
1523
|
+
/** Remove a member (conversation `owner` or team admin), or leave the
|
|
1524
|
+
* chat yourself: `userId` "me" (or your own id) is the self-leave door.
|
|
1525
|
+
* Throws 400 `last_owner` when the target is the roster's last owner and
|
|
1526
|
+
* 400 `creator_cannot_leave` when the chat's creator tries to leave it. */
|
|
1341
1527
|
async removeConversationMember(conversationId: string, userId: string): Promise<ConversationMember[]> {
|
|
1342
1528
|
const body = await this.fetch<{ members: ConversationMember[] }>(
|
|
1343
1529
|
`/api/v1/conversations/${encodeURIComponent(conversationId)}/members/${encodeURIComponent(userId)}`,
|
|
@@ -1497,6 +1683,13 @@ export class AgentComposeClient {
|
|
|
1497
1683
|
};
|
|
1498
1684
|
}
|
|
1499
1685
|
|
|
1686
|
+
/** The credential's user role on the active team; null for a creator-less
|
|
1687
|
+
* key or a user with no membership. */
|
|
1688
|
+
async getTeamRole(): Promise<string | null> {
|
|
1689
|
+
const body = await this.fetch<{ role: string | null }>("/api/v1/team/role");
|
|
1690
|
+
return body.role;
|
|
1691
|
+
}
|
|
1692
|
+
|
|
1500
1693
|
/** List the human members of your team — the people you (or an agent) can
|
|
1501
1694
|
* @-flag with `createMentions`. Each row's `userId` is what
|
|
1502
1695
|
* `mentionedUserIds` expects. */
|
|
@@ -1682,9 +1875,16 @@ export class AgentComposeClient {
|
|
|
1682
1875
|
|
|
1683
1876
|
/** Rename a project (requires `write` role). */
|
|
1684
1877
|
async renameProject(id: string, name: string): Promise<Project> {
|
|
1878
|
+
return this.updateProject(id, { name });
|
|
1879
|
+
}
|
|
1880
|
+
|
|
1881
|
+
/** Change a project's name, tier, description or dates (one PATCH; see
|
|
1882
|
+
* ProjectUpdate for who may set what). 400 `date_order` when the target
|
|
1883
|
+
* date would come before the start date. */
|
|
1884
|
+
async updateProject(id: string, patch: ProjectUpdate): Promise<Project> {
|
|
1685
1885
|
const body = await this.fetch<{ project: Project }>(
|
|
1686
1886
|
`/api/v1/projects/${encodeURIComponent(id)}`,
|
|
1687
|
-
{ method: "PATCH", body:
|
|
1887
|
+
{ method: "PATCH", body: patch },
|
|
1688
1888
|
);
|
|
1689
1889
|
return body.project;
|
|
1690
1890
|
}
|
|
@@ -1718,7 +1918,11 @@ export class AgentComposeClient {
|
|
|
1718
1918
|
return body.members;
|
|
1719
1919
|
}
|
|
1720
1920
|
|
|
1721
|
-
/** Remove a member — project owner/team admin, or self-leave.
|
|
1921
|
+
/** Remove a member — project owner/team admin, or self-leave (`me`).
|
|
1922
|
+
* Leaving a project takes its chats with it: the person loses their row
|
|
1923
|
+
* in every chat filed in the project, public and private, except a chat
|
|
1924
|
+
* they reach through another project they remain in, the home room, a
|
|
1925
|
+
* chat they created, and a chat they are the last owner of. Throws 400
|
|
1722
1926
|
* `last_owner` when the target is the roster's last owner. */
|
|
1723
1927
|
async removeProjectMember(id: string, userId: string): Promise<ProjectMember[]> {
|
|
1724
1928
|
const body = await this.fetch<{ members: ProjectMember[] }>(
|
|
@@ -1728,6 +1932,14 @@ export class AgentComposeClient {
|
|
|
1728
1932
|
return body.members;
|
|
1729
1933
|
}
|
|
1730
1934
|
|
|
1935
|
+
/** What leaving the project would take from the caller: the chats they
|
|
1936
|
+
* lose with it, and the project's shared files and folders. */
|
|
1937
|
+
async leaveProjectPreview(id: string): Promise<{ chats: number; files: number }> {
|
|
1938
|
+
return this.fetch<{ chats: number; files: number }>(
|
|
1939
|
+
`/api/v1/projects/${encodeURIComponent(id)}/leave-preview`,
|
|
1940
|
+
);
|
|
1941
|
+
}
|
|
1942
|
+
|
|
1731
1943
|
/** Change a member's role (project owner or team admin). Throws 400
|
|
1732
1944
|
* `last_owner` when demoting the roster's last owner. */
|
|
1733
1945
|
async setProjectMemberRole(
|
|
@@ -1742,15 +1954,56 @@ export class AgentComposeClient {
|
|
|
1742
1954
|
return body.members;
|
|
1743
1955
|
}
|
|
1744
1956
|
|
|
1745
|
-
/** List a project's objects (member only), newest first. Cursor-paginated.
|
|
1746
|
-
|
|
1957
|
+
/** List a project's objects (member only), newest first. Cursor-paginated.
|
|
1958
|
+
* `type` narrows to one object kind at the server, under the same
|
|
1959
|
+
* cursor — `"conversation"` is a project's chats alone, however many
|
|
1960
|
+
* files it holds. */
|
|
1961
|
+
listProjectObjects(id: string, opts?: { cursor?: string; type?: ProjectObject["type"] }): Promise<ProjectObjectsPage> {
|
|
1747
1962
|
const q = new URLSearchParams();
|
|
1748
1963
|
if (opts?.cursor) q.set("cursor", opts.cursor);
|
|
1964
|
+
if (opts?.type) q.set("type", opts.type);
|
|
1749
1965
|
return this.fetch<ProjectObjectsPage>(
|
|
1750
1966
|
`/api/v1/projects/${encodeURIComponent(id)}/objects${q.toString() ? `?${q}` : ""}`,
|
|
1751
1967
|
);
|
|
1752
1968
|
}
|
|
1753
1969
|
|
|
1970
|
+
/** How many objects of each kind the project holds for the caller
|
|
1971
|
+
* (member only): the whole project's counts, where a page of
|
|
1972
|
+
* `listProjectObjects` holds at most fifty. */
|
|
1973
|
+
getProjectObjectCounts(id: string): Promise<ProjectObjectCounts> {
|
|
1974
|
+
return this.fetch<ProjectObjectCounts>(`/api/v1/projects/${encodeURIComponent(id)}/objects/counts`);
|
|
1975
|
+
}
|
|
1976
|
+
|
|
1977
|
+
/** The project status view (member only): its outcome threads with their
|
|
1978
|
+
* plans, workers, people and next dates, the project's progress, finish
|
|
1979
|
+
* line and next check-in, and what moved lately. `threads` is
|
|
1980
|
+
* cursor-paginated; `recentlyClosed` rides the first page. */
|
|
1981
|
+
getProjectStatus(id: string, opts?: { cursor?: string; limit?: number }): Promise<ProjectStatus> {
|
|
1982
|
+
const q = new URLSearchParams();
|
|
1983
|
+
if (opts?.cursor) q.set("cursor", opts.cursor);
|
|
1984
|
+
if (opts?.limit) q.set("limit", String(opts.limit));
|
|
1985
|
+
return this.fetch<ProjectStatus>(
|
|
1986
|
+
`/api/v1/projects/${encodeURIComponent(id)}/status${q.toString() ? `?${q}` : ""}`,
|
|
1987
|
+
);
|
|
1988
|
+
}
|
|
1989
|
+
|
|
1990
|
+
/** One thread's status for the inline expansion of a status row: its
|
|
1991
|
+
* summary, workers by state, to-dos and last events. 404 for a thread
|
|
1992
|
+
* the caller cannot read. */
|
|
1993
|
+
getThreadStatus(threadId: string): Promise<ThreadStatus> {
|
|
1994
|
+
return this.fetch<ThreadStatus>(`/api/v1/threads/${encodeURIComponent(threadId)}/status`);
|
|
1995
|
+
}
|
|
1996
|
+
|
|
1997
|
+
/** The caller's personal status in the current workspace: the threads
|
|
1998
|
+
* relevant to them (posted, mentioned, asked, a to-do, or in the chat),
|
|
1999
|
+
* grouped client-side by project. `threads` is cursor-paginated. */
|
|
2000
|
+
getMeStatus(opts?: { cursor?: string; limit?: number }): Promise<MeStatus> {
|
|
2001
|
+
const q = new URLSearchParams();
|
|
2002
|
+
if (opts?.cursor) q.set("cursor", opts.cursor);
|
|
2003
|
+
if (opts?.limit) q.set("limit", String(opts.limit));
|
|
2004
|
+
return this.fetch<MeStatus>(`/api/v1/me/status${q.toString() ? `?${q}` : ""}`);
|
|
2005
|
+
}
|
|
2006
|
+
|
|
1754
2007
|
/** DRY-RUN preview of a session add: the files that WOULD be shared (from
|
|
1755
2008
|
* the caller's owned scopes) + any owned-but-skipped entries (paths
|
|
1756
2009
|
* concealed from the caller are omitted). Powers the consent dialog. Same
|
|
@@ -1914,6 +2167,28 @@ export class AgentComposeClient {
|
|
|
1914
2167
|
return body.links;
|
|
1915
2168
|
}
|
|
1916
2169
|
|
|
2170
|
+
/** Create a repo whose origin IS Agent Compose (`manage` scope) — no
|
|
2171
|
+
* GitHub behind it; clone/fetch/push ride the platform git door. 409
|
|
2172
|
+
* names the missing prerequisite (graph drive, git plane) or an
|
|
2173
|
+
* overlapping placement. */
|
|
2174
|
+
async createNativeRepo(
|
|
2175
|
+
input: CreateNativeRepoInput, opts?: { factorySlug?: string },
|
|
2176
|
+
): Promise<CreateNativeRepoResult> {
|
|
2177
|
+
const slug = opts?.factorySlug ?? DEFAULT_FACTORY;
|
|
2178
|
+
return this.fetch<CreateNativeRepoResult>(
|
|
2179
|
+
`/api/v1/factories/${encodeURIComponent(slug)}/repo-links/native`,
|
|
2180
|
+
{ method: "POST", body: input });
|
|
2181
|
+
}
|
|
2182
|
+
|
|
2183
|
+
/** The caller's own connector grants and the workspace's GitHub
|
|
2184
|
+
* installations (metadata only — never tokens; a teammate's other
|
|
2185
|
+
* accounts never come back). Used by `agentc repos link` to default
|
|
2186
|
+
* `--grant` when the team holds exactly one active GitHub grant. */
|
|
2187
|
+
async listConnectorGrants(): Promise<ConnectorGrantSummary[]> {
|
|
2188
|
+
const body = await this.fetch<{ data: ConnectorGrantSummary[] }>("/api/v1/connectors");
|
|
2189
|
+
return body.data;
|
|
2190
|
+
}
|
|
2191
|
+
|
|
1917
2192
|
/** Unlink (§6.3: the prefix's files and history stay on the drive). */
|
|
1918
2193
|
deleteRepoLink(linkId: string, opts?: { factorySlug?: string }): Promise<void> {
|
|
1919
2194
|
const slug = opts?.factorySlug ?? DEFAULT_FACTORY;
|
|
@@ -1986,26 +2261,89 @@ export class AgentComposeClient {
|
|
|
1986
2261
|
* toolbelt credential (the in-sandbox agent's door) or by a session
|
|
1987
2262
|
* writer. */
|
|
1988
2263
|
requestSessionSecrets(
|
|
1989
|
-
conversationId: string, keys: string[],
|
|
2264
|
+
conversationId: string, keys: string[],
|
|
2265
|
+
opts?: {
|
|
2266
|
+
reason?: string; setLabel?: string; kind?: VaultRequestKind; shapes?: Record<string, VaultKeyShape>;
|
|
2267
|
+
savedEntry?: RequestedVaultEntry;
|
|
2268
|
+
/** A REPLACEMENT: the keys are held already and did not work; the card
|
|
2269
|
+
* asks for a new value of the same key. */
|
|
2270
|
+
replace?: boolean;
|
|
2271
|
+
/** A different credential of a kind the work already holds under
|
|
2272
|
+
* another name (the server refuses such an ask without it). */
|
|
2273
|
+
distinct?: boolean;
|
|
2274
|
+
},
|
|
1990
2275
|
): Promise<SessionSecretRequestCreated> {
|
|
1991
2276
|
return this.fetch(
|
|
1992
2277
|
`/api/v1/conversations/${encodeURIComponent(conversationId)}/secret-requests`,
|
|
1993
|
-
{ method: "POST", body: {
|
|
2278
|
+
{ method: "POST", body: {
|
|
2279
|
+
keys,
|
|
2280
|
+
...(opts?.reason ? { reason: opts.reason } : {}),
|
|
2281
|
+
// Suggested batch name — prefills the vault form's save-as-set label.
|
|
2282
|
+
...(opts?.setLabel ? { setLabel: opts.setLabel } : {}),
|
|
2283
|
+
// WHAT KIND of credential — the vault page leads with the user's
|
|
2284
|
+
// matching STANDING entries (personal-vault reuse, 2026-08-31).
|
|
2285
|
+
...(opts?.kind ? { kind: opts.kind } : {}),
|
|
2286
|
+
// WHICH standing entry — by label and/or a card's last four — so the
|
|
2287
|
+
// card and the vault page lead with that exact one.
|
|
2288
|
+
...(opts?.savedEntry ? { savedEntry: opts.savedEntry } : {}),
|
|
2289
|
+
// Per-key DELIVERY (brokered onto a host, or injected) — required
|
|
2290
|
+
// for every key of an api_key ask.
|
|
2291
|
+
...(opts?.shapes ? { shapes: opts.shapes } : {}),
|
|
2292
|
+
...(opts?.replace ? { replace: true } : {}),
|
|
2293
|
+
...(opts?.distinct ? { distinct: true } : {}),
|
|
2294
|
+
} });
|
|
2295
|
+
}
|
|
2296
|
+
|
|
2297
|
+
/** The session's STANDING-vault catalog (2026-08-31): entries the vault
|
|
2298
|
+
* could grant to this session — labels, kinds, field NAMES, last-used.
|
|
2299
|
+
* Values are write-only and never on this wire. Query it BEFORE asking
|
|
2300
|
+
* the human for a credential: a matching entry means the ask is a GRANT
|
|
2301
|
+
* ask naming it, never a blank re-entry form. For the session's own key
|
|
2302
|
+
* it also carries `reaches`: what the session already reaches with no
|
|
2303
|
+
* credential asked for (`agentc access`), so a need met there is never
|
|
2304
|
+
* a vault ask. */
|
|
2305
|
+
getSessionVaultCatalog(conversationId: string): Promise<{ entries: VaultCatalogEntry[]; note?: string; reaches?: string }> {
|
|
2306
|
+
return this.fetch(
|
|
2307
|
+
`/api/v1/conversations/${encodeURIComponent(conversationId)}/vault-catalog`);
|
|
1994
2308
|
}
|
|
1995
2309
|
|
|
1996
2310
|
/** Poll a vault link's status (`pending` → `fulfilled`; `expired` when the
|
|
1997
|
-
* clock ran out
|
|
2311
|
+
* clock ran out; `cancelled` when the human denied it or the requester
|
|
2312
|
+
* withdrew it — attribution rides the answer). The in-sandbox
|
|
2313
|
+
* `agentc secrets session request --wait` loop. */
|
|
1998
2314
|
getSessionSecretRequest(conversationId: string, requestId: string): Promise<SessionSecretRequestStatus> {
|
|
1999
2315
|
return this.fetch(
|
|
2000
2316
|
`/api/v1/conversations/${encodeURIComponent(conversationId)}/secret-requests/${encodeURIComponent(requestId)}`);
|
|
2001
2317
|
}
|
|
2002
2318
|
|
|
2319
|
+
/** List a session's OPEN vault requests (pending + unexpired), newest
|
|
2320
|
+
* first — receipts only (keys, reason, clocks). The cancel verb's
|
|
2321
|
+
* `--all` enumeration. */
|
|
2322
|
+
async listSessionSecretRequests(conversationId: string): Promise<SessionSecretRequestSummary[]> {
|
|
2323
|
+
const body = await this.fetch<{ requests: SessionSecretRequestSummary[] }>(
|
|
2324
|
+
`/api/v1/conversations/${encodeURIComponent(conversationId)}/secret-requests`);
|
|
2325
|
+
return body.requests;
|
|
2326
|
+
}
|
|
2327
|
+
|
|
2328
|
+
/** Cancel one vault request (task #111). The requesting agent withdraws
|
|
2329
|
+
* its own ask (session toolbelt key), or a session writer denies it.
|
|
2330
|
+
* 409 `request_not_pending` when it already settled. */
|
|
2331
|
+
cancelSessionSecretRequest(
|
|
2332
|
+
conversationId: string, requestId: string, opts?: { reason?: string },
|
|
2333
|
+
): Promise<{ requestId: string; status: "cancelled" }> {
|
|
2334
|
+
return this.fetch(
|
|
2335
|
+
`/api/v1/conversations/${encodeURIComponent(conversationId)}/secret-requests/${encodeURIComponent(requestId)}/cancel`,
|
|
2336
|
+
{ method: "POST", body: { ...(opts?.reason ? { reason: opts.reason } : {}) } });
|
|
2337
|
+
}
|
|
2338
|
+
|
|
2003
2339
|
// ── API keys ───────────────────────────────────────────────────────────────
|
|
2004
2340
|
// Both endpoints require an admin-scoped key as the bearer token.
|
|
2005
2341
|
|
|
2006
2342
|
/** Create a new API key on the caller's team. The plaintext `key` is
|
|
2007
2343
|
* returned once — it cannot be retrieved later.
|
|
2008
2344
|
*
|
|
2345
|
+
* `scopes` omitted mints `read` alone; every scope asked for must be one
|
|
2346
|
+
* the caller holds (a key carries no more than whoever mints it).
|
|
2009
2347
|
* When `factorySlug` is set, the new key is restricted to that factory.
|
|
2010
2348
|
* Factory-scoped keys can only mint other keys bound to the same factory. */
|
|
2011
2349
|
createApiKey(input: CreateApiKeyInput): Promise<ApiKeyCreated> {
|