@primusclaw/personal-agent 0.7.1 → 0.8.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/dist/index.js +360 -160
- package/dist/types/assistant/citations.d.ts +5 -5
- package/dist/types/assistant/events.d.ts +4 -3
- package/dist/types/assistant/files.d.ts +5 -2
- package/dist/types/assistant/receipt.d.ts +10 -4
- package/dist/types/assistant/receipts.d.ts +2 -0
- package/dist/types/assistant/say.d.ts +3 -1
- package/dist/types/assistant/tracked-stream.d.ts +1 -0
- package/dist/types/capabilities/help.d.ts +2 -0
- package/dist/types/claw/message-text.d.ts +10 -14
- package/dist/types/feedback/issue-text.d.ts +2 -1
- package/dist/types/feedback/thumbs.d.ts +5 -2
- package/dist/types/index.d.ts +1 -1
- package/dist/types/language/chosen.d.ts +1 -1
- package/dist/types/locales/account.d.ts +3 -1
- package/dist/types/locales/group.d.ts +4 -1
- package/dist/types/locales/link.d.ts +14 -3
- package/dist/types/locales/review-github.d.ts +9 -6
- package/dist/types/locales/transparency.d.ts +8 -3
- package/dist/types/observe/command.d.ts +5 -2
- package/dist/types/ports/claw/sessions.d.ts +7 -0
- package/dist/types/ports/claw/settings.d.ts +8 -3
- package/dist/types/ports/github.d.ts +5 -4
- package/dist/types/ports/store/remote.d.ts +8 -0
- package/dist/types/ports/surface.d.ts +35 -1
- package/dist/types/protocol/claw-api/notifications.d.ts +11 -0
- package/dist/types/remote/permissions.d.ts +5 -0
- package/dist/types/review/service/notices.d.ts +5 -2
- package/dist/types/review/service/request.d.ts +2 -0
- package/dist/types/routing/features.d.ts +2 -0
- package/dist/types/routing/turn-runner.d.ts +2 -2
- package/dist/types/routing/turn-start.d.ts +22 -8
- package/dist/types/routing/views.d.ts +2 -1
- package/dist/types/subscriptions/subscriptions.d.ts +10 -1
- package/dist/types/turn/files.d.ts +6 -2
- package/dist/types/turn/ports.d.ts +1 -1
- package/dist/types/turn/progress/status-message.d.ts +3 -1
- package/dist/types/typed-answer/prompt.d.ts +3 -2
- package/dist/types/understanding/context.d.ts +5 -0
- package/dist/types/understanding/people.d.ts +9 -4
- package/package.json +1 -1
|
@@ -10,7 +10,7 @@
|
|
|
10
10
|
*/
|
|
11
11
|
import type { Citation } from "../ports/surface.js";
|
|
12
12
|
export { CITATION_NAME_MAX, SOURCE_TITLE_INPUT_MAX, SOURCE_URL_MAX, sourceName } from "./citation-sources.js";
|
|
13
|
-
/**
|
|
13
|
+
/** The citations kept of a reply when the channel's own limit is not given (`SurfaceCaps.citationsMax`). */
|
|
14
14
|
export declare const CITATIONS_MAX = 20;
|
|
15
15
|
export declare const CITATION_ABSTRACT_MAX = 160;
|
|
16
16
|
/** What a source's `kind` is shown as on its card; any other kind is "Source". */
|
|
@@ -28,11 +28,11 @@ export declare function makesLink(text: string): boolean;
|
|
|
28
28
|
*/
|
|
29
29
|
export declare function citedNumbers(text: string): Set<number>;
|
|
30
30
|
/**
|
|
31
|
-
* The
|
|
32
|
-
*
|
|
33
|
-
* in the text is left out.
|
|
31
|
+
* The citations of an assistant reply: one per source it carries (`[{n, url, title, kind}]`) whose `[n]` the text has,
|
|
32
|
+
* in number order, at most `max` (the channel's `SurfaceCaps.citationsMax`). A source that is not well formed, repeats a
|
|
33
|
+
* number or is not cited in the text is left out.
|
|
34
34
|
*
|
|
35
35
|
* One difference from Python, which JSON parsing makes: `{"n": 1.0}` is a float there (refused) and the number 1 here
|
|
36
36
|
* (accepted).
|
|
37
37
|
*/
|
|
38
|
-
export declare function citationsFromSources(text: string, sources: unknown): Citation[];
|
|
38
|
+
export declare function citationsFromSources(text: string, sources: unknown, max?: number): Citation[];
|
|
@@ -10,7 +10,7 @@ import type { SuggestedReply } from "../direct-chat/direct-chat.js";
|
|
|
10
10
|
export declare const PULL_LINK: RegExp;
|
|
11
11
|
/** Code points of one of Claw's suggested replies (Claw sends at most 30): a button's few words. */
|
|
12
12
|
export declare const SUGGESTED_REPLY_MAX = 30;
|
|
13
|
-
/**
|
|
13
|
+
/** The suggested replies kept under a message when the channel's own limit is not given (`SurfaceCaps.suggestionsMax`). */
|
|
14
14
|
export declare const SUGGESTIONS_MAX = 3;
|
|
15
15
|
/** The writes Claw holds for the person that this worker draws as a card. */
|
|
16
16
|
export declare const CONFIRM_KINDS: readonly ["trigger_create", "trigger_cancel", "devenv_send", "github_comment", "devenv_hide"];
|
|
@@ -38,9 +38,10 @@ export interface ConfirmWrite {
|
|
|
38
38
|
export declare function confirmWriteOf(event: Event): ConfirmWrite | undefined;
|
|
39
39
|
/**
|
|
40
40
|
* The suggested replies under an `assistant.say` (none under anything else, or with the style off): Claw's own, each one plain
|
|
41
|
-
* line that is no command
|
|
41
|
+
* line that is no command (at most `max`, the channel's `SurfaceCaps.suggestionsMax`), else the defaults in the person's
|
|
42
|
+
* language (`lang`; without it, the language of `text`).
|
|
42
43
|
*/
|
|
43
|
-
export declare function suggestedRepliesOf(event: Event, text: string, styleOn: boolean, lang?: Lang): SuggestedReply[];
|
|
44
|
+
export declare function suggestedRepliesOf(event: Event, text: string, styleOn: boolean, lang?: Lang, max?: number): SuggestedReply[];
|
|
44
45
|
/** The fewest options a choice card shows (Claw sends from 2). */
|
|
45
46
|
export declare const CHOICE_OPTIONS_MIN = 2;
|
|
46
47
|
/** The most options a choice card shows (Claw sends at most 10). */
|
|
@@ -15,8 +15,11 @@ export interface MessageFiles {
|
|
|
15
15
|
fetched: FetchedUpload[];
|
|
16
16
|
failed: [name: string, why: string][];
|
|
17
17
|
}>;
|
|
18
|
-
/**
|
|
19
|
-
|
|
18
|
+
/**
|
|
19
|
+
* The folder under .uploads/ one message's files go to. Not read: core names it itself, under the channel's id
|
|
20
|
+
* (`turn.uploadFolder(messageId, channel)`); kept so an assembly that still supplies it keeps compiling.
|
|
21
|
+
*/
|
|
22
|
+
uploadFolder?(messageId: string): string;
|
|
20
23
|
/** What the person is told about files that did not reach the agent. */
|
|
21
24
|
failedLine(failed: readonly (readonly [string, string])[]): string;
|
|
22
25
|
}
|
|
@@ -3,20 +3,24 @@ import type { Clock } from "../ports/clock.js";
|
|
|
3
3
|
import type { Logger } from "../ports/logger.js";
|
|
4
4
|
import type { MessageId, OutMessage, StreamRefused, UpdateOptions } from "../ports/surface.js";
|
|
5
5
|
import type { Result } from "../result.js";
|
|
6
|
-
/**
|
|
6
|
+
/** The receipt closes itself this long before the channel would close its stream (`SurfaceCaps.streamSeconds`). */
|
|
7
|
+
export declare const RECEIPT_CLOSE_MARGIN_SECONDS = 60;
|
|
8
|
+
/** When the receipt closes itself on a channel that closes a stream 10 minutes after its first request. */
|
|
7
9
|
export declare const RECEIPT_CLOSE_SECONDS: number;
|
|
8
10
|
/** The reply's words streamed into the receipt stop growing here; the reply itself still comes whole. */
|
|
9
11
|
export declare const STREAM_SAY_MAX = 4000;
|
|
10
12
|
/** What the receipt needs of a live stream (a superset of the Surface's `LiveStream`). */
|
|
11
13
|
export interface ReceiptStream {
|
|
12
|
-
/** Still open: no final was sent and
|
|
14
|
+
/** Still open: no final was sent and the channel has not closed it. */
|
|
13
15
|
readonly open: boolean;
|
|
14
16
|
/** The text streamed so far ("" none). */
|
|
15
17
|
readonly streamed: string;
|
|
16
|
-
/** The stream's message id once
|
|
18
|
+
/** The stream's message id once the channel gave one ("" before). */
|
|
17
19
|
readonly streamId: MessageId;
|
|
18
20
|
/** The person's message the stream answers. */
|
|
19
21
|
readonly replyTo: MessageId;
|
|
22
|
+
/** Seconds after its first request that the channel closes the stream (absent: 10 minutes). */
|
|
23
|
+
readonly lifetimeSeconds?: number;
|
|
20
24
|
/** A final may still be refused and then edited into place: the stream has an id and was not closed. */
|
|
21
25
|
readonly closable: boolean;
|
|
22
26
|
/** Seconds since the stream's first request. */
|
|
@@ -97,7 +101,9 @@ export declare class Receipt {
|
|
|
97
101
|
* (`closed()` resolves), so nothing keeps the process up.
|
|
98
102
|
*/
|
|
99
103
|
drop(): void;
|
|
100
|
-
/**
|
|
104
|
+
/** When the receipt closes itself: RECEIPT_CLOSE_MARGIN_SECONDS before the channel would close its stream. */
|
|
105
|
+
private get closeSeconds();
|
|
106
|
+
/** Close the receipt by itself at `closeSeconds` unless a reply closed it first. */
|
|
101
107
|
arm(clock: Clock, stillMine: () => boolean, onClose: () => void): void;
|
|
102
108
|
private closeInTime;
|
|
103
109
|
/** The reply's words this receipt shows, final: nothing more is shown in it from now on. */
|
|
@@ -54,6 +54,8 @@ export declare class ReceiptConversation implements Conversation {
|
|
|
54
54
|
private postscript;
|
|
55
55
|
constructor(inner: Conversation, receipts: Receipts, receipt: Receipt | undefined, postscript?: readonly string[]);
|
|
56
56
|
get ref(): import("../ports/surface.js").ConversationRef;
|
|
57
|
+
get caps(): import("../ports/surface.js").SurfaceCaps;
|
|
58
|
+
get replyTo(): string;
|
|
57
59
|
get edited(): ReadonlySet<string>;
|
|
58
60
|
markSettled(id: MessageId): void;
|
|
59
61
|
typing(): Promise<void>;
|
|
@@ -14,7 +14,7 @@
|
|
|
14
14
|
*/
|
|
15
15
|
import type { SuggestedReply } from "../direct-chat/direct-chat.js";
|
|
16
16
|
import type { StorePort } from "../ports/store/index.js";
|
|
17
|
-
import type { OutMessage } from "../ports/surface.js";
|
|
17
|
+
import type { OutMessage, SurfaceLimits } from "../ports/surface.js";
|
|
18
18
|
export type SayStore = Pick<StorePort, "prefs" | "assistantCards" | "assistantButtons">;
|
|
19
19
|
/** (worker session, delivery id) -> Claw's download link, or null. */
|
|
20
20
|
export type DeliveryLink = (sessionId: string, deliveryId: string) => string | null;
|
|
@@ -26,6 +26,8 @@ export interface SayOptions {
|
|
|
26
26
|
readonly head?: string;
|
|
27
27
|
/** Suggested replies of the worker's own, before Claw's. */
|
|
28
28
|
readonly replies?: readonly SuggestedReply[];
|
|
29
|
+
/** How many citations and suggested replies the channel shows (the conversation's `caps`). */
|
|
30
|
+
readonly limits?: Pick<SurfaceLimits, "citationsMax" | "suggestionsMax">;
|
|
29
31
|
}
|
|
30
32
|
export interface SayDeps {
|
|
31
33
|
readonly store: SayStore;
|
|
@@ -19,6 +19,7 @@ export declare class TrackedStream implements ReceiptStream {
|
|
|
19
19
|
constructor(live: LiveStream, conversation: Conversation, replyTo: MessageId, clock: Clock);
|
|
20
20
|
/** A final may still be refused and then edited into place: the channel gave the stream an id and it was not closed. */
|
|
21
21
|
get closable(): boolean;
|
|
22
|
+
get lifetimeSeconds(): number;
|
|
22
23
|
ageSeconds(): number;
|
|
23
24
|
inform(text: string, options?: UpdateOptions): Promise<Result<void, StreamRefused>>;
|
|
24
25
|
emit(text: string, options?: UpdateOptions): Promise<Result<void, StreamRefused>>;
|
|
@@ -22,6 +22,8 @@ export interface HelpOptions {
|
|
|
22
22
|
readonly understanding?: boolean;
|
|
23
23
|
/** The deployment keeps a group's recent messages as background (what the data statement then says it sees). */
|
|
24
24
|
readonly groupContext?: GroupContextKept;
|
|
25
|
+
/** The chat app's full name (`SurfaceCaps.name`): where the data statement says messages go through. */
|
|
26
|
+
readonly channel?: string;
|
|
25
27
|
}
|
|
26
28
|
/** The help for a chat, in `language` ("zh", or anything else for English). */
|
|
27
29
|
export declare function renderHelp(language: string, options?: HelpOptions): string;
|
|
@@ -1,28 +1,24 @@
|
|
|
1
|
-
/**
|
|
2
|
-
|
|
3
|
-
* for a change summary (the phone has no diff view), then the reply-style rule a Claw rule tool holds.
|
|
4
|
-
*/
|
|
5
|
-
/** What the reply-style rule is introduced with. */
|
|
6
|
-
export declare const RULE_HEADING = "## Teams reply style (formatting only, facts unchanged)";
|
|
1
|
+
/** What the reply-style rule is introduced with, e.g. "## Teams reply style (formatting only, facts unchanged)". */
|
|
2
|
+
export declare function ruleHeading(channel: string): string;
|
|
7
3
|
/** What the change-summary request is introduced with. */
|
|
8
|
-
export declare
|
|
4
|
+
export declare function changeHeading(channel: string): string;
|
|
9
5
|
/** The change-summary request: about the answer's last lines, not a style, so it is kept apart from the rule. */
|
|
10
6
|
export declare const CHANGE_SUMMARY_RULE: string;
|
|
11
7
|
/** Exactly what the worker appends first, whether or not a rule follows. */
|
|
12
|
-
export declare
|
|
8
|
+
export declare function changeSection(channel: string): string;
|
|
13
9
|
/** A rule is edited in Claw; a changed rule reaches the chat within this. */
|
|
14
10
|
export declare const RULE_TTL_MS = 600000;
|
|
15
11
|
/** A reply-style rule is about 1 KB; anything this large is not one. */
|
|
16
12
|
export declare const RULE_MAX_BYTES = 32768;
|
|
17
13
|
/**
|
|
18
|
-
* `text` as the person wrote it, with what the worker appended taken off again
|
|
19
|
-
* always the first thing appended, so it marks where the person's own words
|
|
20
|
-
* everything from it on goes. A message from before the request existed has only
|
|
21
|
-
* heading first starts.
|
|
14
|
+
* `text` as the person wrote it, with what the worker appended taken off again, whichever chat app's name the headings
|
|
15
|
+
* carry. The change summary is a fixed text and always the first thing appended, so it marks where the person's own words
|
|
16
|
+
* end: it is looked for from the end, and everything from it on goes. A message from before the request existed has only
|
|
17
|
+
* the rule: it is cut where the rule's heading first starts.
|
|
22
18
|
*/
|
|
23
19
|
export declare function withoutRule(text: string): string;
|
|
24
20
|
/**
|
|
25
21
|
* The content of a message to a plain session: the person's text, then the change-summary request (only where a rule
|
|
26
|
-
* tool is configured), then the rule when there is one.
|
|
22
|
+
* tool is configured), then the rule when there is one. `channel`: the chat app's short name the headings carry.
|
|
27
23
|
*/
|
|
28
|
-
export declare function messageContent(text: string, rule: string, withRuleTool: boolean): string;
|
|
24
|
+
export declare function messageContent(text: string, rule: string, withRuleTool: boolean, channel: string): string;
|
|
@@ -7,7 +7,8 @@
|
|
|
7
7
|
export type Mask = (text: string) => string;
|
|
8
8
|
export declare const FEEDBACK_LABEL = "clawy-feedback";
|
|
9
9
|
export declare const LABEL_COLOR = "d93f0b";
|
|
10
|
-
|
|
10
|
+
/** The feedback label's description: who reports, from the chat app `channel` (`SurfaceCaps.shortName`, e.g. "Teams"). */
|
|
11
|
+
export declare function labelDescription(channel: string): string;
|
|
11
12
|
export declare const MAX_TEXT_CHARS = 4000;
|
|
12
13
|
/** How the deployment names itself and where its users talk to it. */
|
|
13
14
|
export interface IssueWording {
|
|
@@ -29,8 +29,11 @@ export interface ThumbsDeps {
|
|
|
29
29
|
readonly mask: Mask;
|
|
30
30
|
readonly log: Logger;
|
|
31
31
|
}
|
|
32
|
-
/**
|
|
33
|
-
|
|
32
|
+
/**
|
|
33
|
+
* The key a thumb is stored under in Claw: `<channel>:<message id>` (`channel` is `SurfaceCaps.channel`, e.g.
|
|
34
|
+
* `teams:<activity id>`), hashed when Claw would refuse it as it is.
|
|
35
|
+
*/
|
|
36
|
+
export declare function voteMessageId(sha256Hex: (text: string) => string, messageId: string, channel: string): string | undefined;
|
|
34
37
|
export declare class FeedbackThumbs {
|
|
35
38
|
private readonly deps;
|
|
36
39
|
private readonly counts;
|
package/dist/types/index.d.ts
CHANGED
|
@@ -13,7 +13,7 @@ export * from "./own.js";
|
|
|
13
13
|
export * from "./guardrails/index.js";
|
|
14
14
|
export * from "./limits/index.js";
|
|
15
15
|
export * from "./review-text/index.js";
|
|
16
|
-
export {
|
|
16
|
+
export { intentPrompt, modePrompt } from "./locales/review-github.js";
|
|
17
17
|
export * from "./typed-answer/index.js";
|
|
18
18
|
export * from "./understanding/index.js";
|
|
19
19
|
export * from "./locales/index.js";
|
|
@@ -6,7 +6,7 @@
|
|
|
6
6
|
* choice, nothing is sent, and Claw reads the language from the message as before. To the assistant the choice goes in the
|
|
7
7
|
* message's `channel_context` (`reply_language`); to a plain session (a 1:1 chat without the assistant) as the line Claw's
|
|
8
8
|
* assistant uses for it, after the message (`replyLanguageLine`). A group's turn carries the group's language in that line
|
|
9
|
-
* instead (`groupChosenLang`): in a group a person's own choice is not read.
|
|
9
|
+
* instead (`groupChosenLang`), or with none set the language the asker writes in: in a group a person's own choice is not read.
|
|
10
10
|
*/
|
|
11
11
|
import type { Lang } from "../locales/lang.js";
|
|
12
12
|
/** What of a person's preferences says the choice (`Prefs.lang`, `Prefs.langSet`). */
|
|
@@ -42,7 +42,9 @@ export declare const accountText: import("./catalog.js").Catalog<{
|
|
|
42
42
|
langUsage: string;
|
|
43
43
|
langWhySet: string;
|
|
44
44
|
langWhyWritten: string;
|
|
45
|
-
langWhyClient:
|
|
45
|
+
langWhyClient: (p: {
|
|
46
|
+
channel: string;
|
|
47
|
+
}) => string;
|
|
46
48
|
langIs: (p: {
|
|
47
49
|
name: string;
|
|
48
50
|
why: string;
|
|
@@ -27,7 +27,10 @@ export declare const onboardingText: {
|
|
|
27
27
|
readonly notYours: (name: string) => string;
|
|
28
28
|
readonly connected: (pending: boolean) => string;
|
|
29
29
|
readonly stepsSent: (bot: string) => string;
|
|
30
|
-
readonly noDm: (page: string
|
|
30
|
+
readonly noDm: (page: string, channel: {
|
|
31
|
+
readonly name: string;
|
|
32
|
+
readonly shortName: string;
|
|
33
|
+
}) => string;
|
|
31
34
|
readonly resuming: (name: string, bot: string) => string;
|
|
32
35
|
readonly notResumed: "I could not start your request in the group chat. Mention me there again to run it.";
|
|
33
36
|
};
|
|
@@ -5,6 +5,7 @@ export declare const linkText: import("./catalog.js").Catalog<{
|
|
|
5
5
|
bot: string;
|
|
6
6
|
page: string;
|
|
7
7
|
notice: string;
|
|
8
|
+
channel: string;
|
|
8
9
|
}) => string;
|
|
9
10
|
platformDown: string;
|
|
10
11
|
notConfirmedYet: string;
|
|
@@ -27,13 +28,23 @@ export declare const linkText: import("./catalog.js").Catalog<{
|
|
|
27
28
|
badCode: string;
|
|
28
29
|
identityRefused: string;
|
|
29
30
|
}>;
|
|
30
|
-
/**
|
|
31
|
-
|
|
31
|
+
/**
|
|
32
|
+
* The console's page that gives a `/link` code for the channel `channel` (`SurfaceCaps.channel`), e.g.
|
|
33
|
+
* `<console>/primus-claw/teams-link`.
|
|
34
|
+
*/
|
|
35
|
+
export declare function linkPage(publicBaseUrl: string, channel: string): string;
|
|
36
|
+
/**
|
|
37
|
+
* The name the linked key has in SaFE (the console creates it under this name): "PrimusClaw " and the channel's short
|
|
38
|
+
* name (`SurfaceCaps.shortName`), e.g. "PrimusClaw Teams".
|
|
39
|
+
*/
|
|
40
|
+
export declare function linkKeyName(shortName: string): string;
|
|
32
41
|
/** `/unlink`. */
|
|
33
42
|
export declare const unlinkText: import("./catalog.js").Catalog<{
|
|
34
43
|
bindingOnly: string;
|
|
35
44
|
deleted: string;
|
|
36
|
-
notDeleted:
|
|
45
|
+
notDeleted: (p: {
|
|
46
|
+
key: string;
|
|
47
|
+
}) => string;
|
|
37
48
|
stillBound: string;
|
|
38
49
|
unlinked: (p: {
|
|
39
50
|
tail: string;
|
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
/** What the model that reads a group's review request is told. */
|
|
2
|
-
export declare const
|
|
3
|
-
/** What the model that reads a 1:1 message about the confirmation setting is told. */
|
|
4
|
-
export declare const
|
|
1
|
+
/** What the model that reads a group's review request is told; `channel`: the chat app's full name (`SurfaceCaps.name`). */
|
|
2
|
+
export declare const intentPrompt: (channel: string) => string;
|
|
3
|
+
/** What the model that reads a 1:1 message about the confirmation setting is told; `channel` as `intentPrompt`'s. */
|
|
4
|
+
export declare const modePrompt: (channel: string) => string;
|
|
5
5
|
/** Claw answers 404 for the confirmation setting: its API is not deployed yet, and the default applies. */
|
|
6
6
|
export declare const NOT_YET_TEXT = "this setting is not available yet (PrimusClaw does not have it yet), so the default applies: a person confirms high-risk changes / \u8FD9\u4E2A\u8BBE\u7F6E\u8FD8\u6CA1\u4E0A\u7EBF\uFF0C\u6682\u6309\u9ED8\u8BA4\uFF1A\u9AD8\u98CE\u9669\u4EBA\u5DE5\u518D\u786E\u8BA4\u4E00\u6B21";
|
|
7
7
|
/** `/github bind` for a binding made with `public_repo` only, before it asks again (`{login}`). */
|
|
@@ -15,5 +15,8 @@ export declare const CONSENT_READS: readonly (readonly [string, string])[];
|
|
|
15
15
|
export declare const HELP_LINES = "\n- \"\u8BF7 XX \u5E2E\u6211 review \u5408\u5165 <PR> [<PR> ...]\" here or in a group (\u79C1\u804A\u6216\u7FA4\u91CC\u90FD\u53EF\u4EE5) has XX review and merge them as XX; naming nobody here means your own account; after I review or merge as you, I tell you in this chat\n- `/github bind` connects your GitHub account, and `/github auto-merge on` lets a colleague (usually a pull request's author) ask me, by your name, to review and merge a pull request as you; `/github mode` (or saying \"\u6539\u6210\u5168\u81EA\u52A8\") chooses whether a person confirms high-risk changes (the default) or merges go fully automatic, for every review with your account; `/github status`, `/github unbind` and `/github auto-merge on|off` manage it";
|
|
16
16
|
export declare const GROUP_HELP_LINES = "\n\nHave a committer review and merge your pull request, here or in a 1:1 chat with me (\u7FA4\u91CC\u6216\u79C1\u804A\u90FD\u53EF\u4EE5): `@Clawy \u8BF7 XX \u5E2E\u6211 review \u5408\u5165 <PR link or owner/repo#N>` (a public AMD-AGI pull request). XX has to be named, and I act only with XX's own connected GitHub account, never yours or anyone else's. XX authorizes me once (`/github bind` and `/github auto-merge on`, in a 1:1 chat); without that I do nothing with XX's account and say so. A change to architecture, interfaces, security, CI or dependencies waits for XX's own confirmation. `/github` itself works only in a 1:1 chat.";
|
|
17
17
|
export declare const USAGE = "`/github bind` connects your GitHub account, `/github unbind` removes it, `/github status` shows it, `/github auto-merge on|off` is your standing permission for colleagues to ask me (by your name) to review and merge for you, or not, and `/github mode` chooses how reviews and merges with your account are confirmed: a person confirms high-risk changes (the default), or fully automatic.";
|
|
18
|
-
/**
|
|
19
|
-
|
|
18
|
+
/**
|
|
19
|
+
* Why a reviewer cannot be reached by what waits for them, and what they can do about it: said to the asker. `channel`:
|
|
20
|
+
* the chat app's short name (`SurfaceCaps.shortName`).
|
|
21
|
+
*/
|
|
22
|
+
export declare function reachWords(channel: string): Readonly<Record<string, readonly [string, string]>>;
|
|
@@ -11,7 +11,11 @@ import { type Lang } from "./lang.js";
|
|
|
11
11
|
export type Phrase = Readonly<Record<Lang, string>>;
|
|
12
12
|
export declare const AI_NOTICE: Phrase;
|
|
13
13
|
export declare const DATA_TITLE: Phrase;
|
|
14
|
-
|
|
14
|
+
/**
|
|
15
|
+
* The lines of the data statement in each language. `channel`: the full name of the chat app the messages come through
|
|
16
|
+
* (`SurfaceCaps.name`, e.g. "Microsoft Teams"); without it, "where it goes" names none.
|
|
17
|
+
*/
|
|
18
|
+
export declare function dataLines(channel?: string): Readonly<Record<Lang, readonly string[]>>;
|
|
15
19
|
/** Only where remote agents are on (a 1:1 chat): an attached chat's messages go to the person's own machine, not to PrimusClaw. */
|
|
16
20
|
export declare const REMOTE_LINE: Phrase;
|
|
17
21
|
/**
|
|
@@ -34,6 +38,7 @@ export declare const SEES_LINE: Phrase;
|
|
|
34
38
|
export declare function groupContextLines(lang: Lang, kept: GroupContextKept): readonly string[];
|
|
35
39
|
/**
|
|
36
40
|
* The section of help about answers and data, in `lang`; `remote`: remote agents are on in this chat; `groupContext`:
|
|
37
|
-
* the deployment keeps a group's recent messages (absent: it does not, and a group's @mentions are all it sees)
|
|
41
|
+
* the deployment keeps a group's recent messages (absent: it does not, and a group's @mentions are all it sees);
|
|
42
|
+
* `channel`: the chat app's full name (`SurfaceCaps.name`).
|
|
38
43
|
*/
|
|
39
|
-
export declare function dataStatement(lang: string, remote?: boolean, groupContext?: GroupContextKept): string;
|
|
44
|
+
export declare function dataStatement(lang: string, remote?: boolean, groupContext?: GroupContextKept, channel?: string): string;
|
|
@@ -2,5 +2,8 @@
|
|
|
2
2
|
export type ObserveVerb = "on" | "off" | "status" | "usage";
|
|
3
3
|
/** The command's verb, `usage` for a malformed one, undefined when the text is not this command. */
|
|
4
4
|
export declare function parseObserve(text: string): ObserveVerb | undefined;
|
|
5
|
-
/**
|
|
6
|
-
|
|
5
|
+
/**
|
|
6
|
+
* The scope a group chat is to Claw, `group:<channel>:<id>` (`channel` is `SurfaceCaps.channel`, e.g.
|
|
7
|
+
* `group:teams:19:...@thread.v2`), or undefined when its id cannot be one.
|
|
8
|
+
*/
|
|
9
|
+
export declare function scopeOf(conversationId: string, channel: string): string | undefined;
|
|
@@ -23,6 +23,11 @@ export interface NewSession {
|
|
|
23
23
|
readonly reviewOnly?: boolean;
|
|
24
24
|
/** false: the session is made with no message (`text` is only its name) and `messageId` is "". Default true. */
|
|
25
25
|
readonly withMessage?: boolean;
|
|
26
|
+
/**
|
|
27
|
+
* The short name of the chat app the message came through (`SurfaceCaps.shortName`), which the headings of what the
|
|
28
|
+
* worker appends to it carry ("## Teams reply style ..."); without it they name none.
|
|
29
|
+
*/
|
|
30
|
+
readonly channel?: string;
|
|
26
31
|
/** Other people read the session (a group chat): `config.memory = "off"`. */
|
|
27
32
|
readonly shared?: boolean;
|
|
28
33
|
}
|
|
@@ -36,6 +41,8 @@ export interface UploadFile {
|
|
|
36
41
|
export interface SendOptions {
|
|
37
42
|
/** See `NewSession.modelKey`. */
|
|
38
43
|
readonly modelKey?: string;
|
|
44
|
+
/** See `NewSession.channel`. */
|
|
45
|
+
readonly channel?: string;
|
|
39
46
|
/** The session acts as a user: the message goes as the text alone, without plugin or appended rules. */
|
|
40
47
|
readonly acting?: boolean;
|
|
41
48
|
}
|
|
@@ -28,12 +28,17 @@ export type ClawSubscription = Partial<NotificationSubscription> & {
|
|
|
28
28
|
/** Notification subscriptions (`/v1/notification-subscriptions`). ClawError(404): notifications are off on Claw. */
|
|
29
29
|
export interface ClawNotificationsPort {
|
|
30
30
|
list(key: ClawCredential): Promise<ClawSubscription[]>;
|
|
31
|
-
/**
|
|
32
|
-
|
|
33
|
-
|
|
31
|
+
/**
|
|
32
|
+
* Subscribes the key's owner at `url`; the reply carries the signing secret, once. Empty lists: Claw's defaults. `surface`: the
|
|
33
|
+
* chat surface the subscription delivers to (`teams`, `slack`, ...), which Claw routes the assistant's messages by; absent, Claw's
|
|
34
|
+
* default (Teams). A Claw from before the label ignores it.
|
|
35
|
+
*/
|
|
36
|
+
create(key: ClawCredential, url: string, eventTypes?: readonly string[], sources?: readonly string[], surface?: string): Promise<ClawSubscription>;
|
|
37
|
+
/** Changes which events (and, given, which sources and surface) a subscription gets; `enable` turns it on again. */
|
|
34
38
|
updateTypes(key: ClawCredential, subscriptionId: string, eventTypes: readonly string[], options?: {
|
|
35
39
|
enable?: boolean;
|
|
36
40
|
sources?: readonly string[];
|
|
41
|
+
surface?: string;
|
|
37
42
|
}): Promise<ClawSubscription>;
|
|
38
43
|
delete(key: ClawCredential, subscriptionId: string): Promise<void>;
|
|
39
44
|
}
|
|
@@ -88,10 +88,11 @@ export interface ListedMention {
|
|
|
88
88
|
/**
|
|
89
89
|
* One small model call that says what a message asks for, with the asker's own key. undefined for anything but an answer in
|
|
90
90
|
* time (no model, the gateway refused or was slow): the rules read it instead. `{ intent: null }` when it answered something
|
|
91
|
-
* that is not a JSON object.
|
|
91
|
+
* that is not a JSON object. `channel` is the full name of the chat app the message came through (`SurfaceCaps.name`),
|
|
92
|
+
* which the model is told.
|
|
92
93
|
*/
|
|
93
94
|
export interface IntentReader {
|
|
94
|
-
read(key: string, text: string, mentions: readonly ListedMention[]): Promise<Record<string, unknown> | undefined>;
|
|
95
|
-
readMode(key: string, text: string): Promise<Record<string, unknown> | undefined>;
|
|
96
|
-
readAnswer(key: string, text: string, pending: readonly Readonly<Record<string, string>>[]): Promise<Record<string, unknown> | undefined>;
|
|
95
|
+
read(key: string, text: string, mentions: readonly ListedMention[], channel: string): Promise<Record<string, unknown> | undefined>;
|
|
96
|
+
readMode(key: string, text: string, channel: string): Promise<Record<string, unknown> | undefined>;
|
|
97
|
+
readAnswer(key: string, text: string, pending: readonly Readonly<Record<string, string>>[], channel: string): Promise<Record<string, unknown> | undefined>;
|
|
97
98
|
}
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
/** Remote agents: which session a chat is attached to, how far it has read, and the permission cards it showed
|
|
2
2
|
* (tables `remote_state`, `remote_session_names`, `remote_permissions`). */
|
|
3
|
+
import type { Lang } from "../../locales/lang.js";
|
|
3
4
|
/** 'card': the chat box goes to the assistant and the session card's input to the session; 'chat': all to the session. */
|
|
4
5
|
export type ChatBox = "card" | "chat";
|
|
5
6
|
export interface RemoteState {
|
|
@@ -95,6 +96,11 @@ export interface RemotePermission {
|
|
|
95
96
|
readonly messageId: string;
|
|
96
97
|
/** For a question a terminal asks: the whole `remote.ask`, so the card can be drawn again with its content (null otherwise). */
|
|
97
98
|
readonly ask: Readonly<Record<string, unknown>> | null;
|
|
99
|
+
/**
|
|
100
|
+
* The language its card was shown in ("" for a card shown before it was kept): what the card is edited to later (answered here,
|
|
101
|
+
* at the terminal, given up) and a click on it is told are said in it, never in a language read again from something else.
|
|
102
|
+
*/
|
|
103
|
+
readonly lang: Lang | "";
|
|
98
104
|
}
|
|
99
105
|
export interface NewRemotePermission {
|
|
100
106
|
readonly userId: string;
|
|
@@ -105,6 +111,8 @@ export interface NewRemotePermission {
|
|
|
105
111
|
readonly expiresAt: number;
|
|
106
112
|
/** For a question a terminal asks: the whole `remote.ask` (see {@link RemotePermission.ask}). */
|
|
107
113
|
readonly ask?: Readonly<Record<string, unknown>>;
|
|
114
|
+
/** The language the card is shown in (see {@link RemotePermission.lang}). */
|
|
115
|
+
readonly lang?: Lang;
|
|
108
116
|
}
|
|
109
117
|
export interface RemotePermissionRepository {
|
|
110
118
|
/** Recorded before it is shown; false when this request already has a row. */
|
|
@@ -260,8 +260,33 @@ export interface OutMessage {
|
|
|
260
260
|
readonly suggestions?: readonly SuggestedReply[];
|
|
261
261
|
readonly citations?: readonly Citation[];
|
|
262
262
|
}
|
|
263
|
+
/**
|
|
264
|
+
* Which channel this is, as core names it to Claw, keys what it stores per channel, and says it to a person. Core holds
|
|
265
|
+
* no channel's name of its own: everything it says or stores about the channel comes from here.
|
|
266
|
+
*/
|
|
267
|
+
export interface SurfaceIdentity {
|
|
268
|
+
/**
|
|
269
|
+
* The channel's id: what Claw is told the message came through (`channel_context.channel`), and the prefix of what is
|
|
270
|
+
* kept per channel (a vote's key, a message's upload folder, a group's scope, the console's link page). Lower case
|
|
271
|
+
* letters, digits and "-" only, e.g. "teams".
|
|
272
|
+
*/
|
|
273
|
+
readonly channel: string;
|
|
274
|
+
/** The channel's full name as a person reads it ("Microsoft Teams"). */
|
|
275
|
+
readonly name: string;
|
|
276
|
+
/** Its short name ("Teams"). */
|
|
277
|
+
readonly shortName: string;
|
|
278
|
+
}
|
|
279
|
+
/** How much of a decoration a message carries, and how long a live stream stays open, on this channel. */
|
|
280
|
+
export interface SurfaceLimits {
|
|
281
|
+
/** Citations shown on one message. */
|
|
282
|
+
readonly citationsMax: number;
|
|
283
|
+
/** Suggested replies shown under one message. */
|
|
284
|
+
readonly suggestionsMax: number;
|
|
285
|
+
/** Seconds after its first request that the channel closes a live stream itself. */
|
|
286
|
+
readonly streamSeconds: number;
|
|
287
|
+
}
|
|
263
288
|
/** What the channel can do, so core picks the shape that works instead of trying and failing. */
|
|
264
|
-
export interface SurfaceCaps {
|
|
289
|
+
export interface SurfaceCaps extends SurfaceIdentity, SurfaceLimits {
|
|
265
290
|
/** A live, growing status/answer bubble (`LiveStream`). */
|
|
266
291
|
readonly streaming: boolean;
|
|
267
292
|
/** `post` returns the id of the new message (so it can be edited later). */
|
|
@@ -273,6 +298,8 @@ export interface SurfaceCaps {
|
|
|
273
298
|
readonly citations: boolean;
|
|
274
299
|
readonly suggestions: boolean;
|
|
275
300
|
}
|
|
301
|
+
/** A channel id as `SurfaceIdentity.channel` allows it. */
|
|
302
|
+
export declare const SURFACE_CHANNEL: RegExp;
|
|
276
303
|
/** A message could not be removed (the channel cannot delete, or it refused). The message is still there. */
|
|
277
304
|
export interface DeleteUnsupported {
|
|
278
305
|
readonly kind: "delete_unsupported";
|
|
@@ -322,6 +349,13 @@ export type Envelope = JsonObject;
|
|
|
322
349
|
*/
|
|
323
350
|
export interface Conversation {
|
|
324
351
|
readonly ref: ConversationRef;
|
|
352
|
+
/** The caps of the channel this conversation is on (`Surface.caps`). */
|
|
353
|
+
readonly caps: SurfaceCaps;
|
|
354
|
+
/**
|
|
355
|
+
* The message this conversation's reference was read from (Teams: the reference's activity id): the person's message
|
|
356
|
+
* a live stream for it answers. "" when the reference names none (a new 1:1 chat).
|
|
357
|
+
*/
|
|
358
|
+
readonly replyTo: MessageId;
|
|
325
359
|
/** The messages this conversation has tried to replace (a clicked card is settled when its id is here). */
|
|
326
360
|
readonly edited: ReadonlySet<MessageId>;
|
|
327
361
|
/**
|
|
@@ -20,12 +20,23 @@ export declare const NOTIFICATION_SUBSCRIPTION_EVENT_TYPES: readonly ["run.compl
|
|
|
20
20
|
*/
|
|
21
21
|
export declare const NOTIFICATION_SOURCES: readonly ["trigger", "long_run", "assistant_item"];
|
|
22
22
|
export type NotificationSource = (typeof NOTIFICATION_SOURCES)[number];
|
|
23
|
+
/**
|
|
24
|
+
* The chat surface a subscription delivers to (`surface`) and a message to the assistant came from (`channel_context.channel`):
|
|
25
|
+
* a lowercase label the receiver chooses, such as `teams` or `slack`. An assistant message goes back to the surface the turn's
|
|
26
|
+
* message came from, and a proactive one to the surface the person used last (`api/src/notifications/surfaces.ts`). A subscription
|
|
27
|
+
* or a message that names none is `teams`, which is what every receiver was before the label existed.
|
|
28
|
+
*/
|
|
29
|
+
export declare const NOTIFICATION_SURFACE_DEFAULT = "teams";
|
|
30
|
+
/** What a surface label may be: a lowercase letter, then up to 31 lowercase letters, digits, `-` or `_`. */
|
|
31
|
+
export declare const NOTIFICATION_SURFACE_PATTERN: RegExp;
|
|
23
32
|
/** One subscription, as listed, created (with its signing `secret`, once) and changed. */
|
|
24
33
|
export interface NotificationSubscription<Time = string> {
|
|
25
34
|
subscription_id: string;
|
|
26
35
|
url: string;
|
|
27
36
|
event_types: string[];
|
|
28
37
|
sources: string[];
|
|
38
|
+
/** The surface it delivers to (`NOTIFICATION_SURFACE_DEFAULT` when its receiver named none). Absent from a Claw before the label. */
|
|
39
|
+
surface?: string;
|
|
29
40
|
enabled: boolean;
|
|
30
41
|
consecutive_failures: number;
|
|
31
42
|
created_at: Time;
|
|
@@ -31,6 +31,11 @@ export declare class Permissions {
|
|
|
31
31
|
show(chatKey: string, sessionId: string, request: Readonly<Record<string, unknown>>, to: Conversation): Promise<void>;
|
|
32
32
|
/** The card again with its buttons and `text` on it: the decision did not go through. */
|
|
33
33
|
private reopened;
|
|
34
|
+
/**
|
|
35
|
+
* What a click is told, and what its card becomes, is said in the language the card was shown in (a card Claw's push drew took
|
|
36
|
+
* it from Claw's words, which need not be the person's chosen one); for a card from before that was kept, the person's.
|
|
37
|
+
*/
|
|
38
|
+
private cardLang;
|
|
34
39
|
/** A click on an option of a permission card (see the module). */
|
|
35
40
|
decide(click: Decision): Promise<void>;
|
|
36
41
|
/** Past its time a request is refused, whatever the button says. */
|
|
@@ -31,8 +31,11 @@ export declare class Notices {
|
|
|
31
31
|
/** The reviewer's item waits for them: what it asks and how to answer, with the item's card when it can be read as them. */
|
|
32
32
|
tellReviewerWaiting(review: ReviewTurn, prSummary: string): Promise<void>;
|
|
33
33
|
private waitingText;
|
|
34
|
-
/**
|
|
35
|
-
|
|
34
|
+
/**
|
|
35
|
+
* For a review handed to someone else: '' when what waits for them reaches their chat, else one line for the asker.
|
|
36
|
+
* `channel`: the chat app's short name (`SurfaceCaps.shortName`).
|
|
37
|
+
*/
|
|
38
|
+
reachNote(review: ReviewTurn | undefined, channel: string): Promise<string>;
|
|
36
39
|
/** Sends what `send` says into the person's own chat, at most once a day for this kind; true when they have it. */
|
|
37
40
|
onceADay(person: Actor, via: ConversationRef, kind: string, send: (chat: Conversation) => Promise<void>): Promise<boolean>;
|
|
38
41
|
/** The asker has no Primus key of their own linked, and a review runs on it: one line where asked, and the steps in their chat. */
|
|
@@ -7,6 +7,8 @@ export interface Asking {
|
|
|
7
7
|
readonly message: InboundMessage;
|
|
8
8
|
readonly sender: UserRef;
|
|
9
9
|
readonly group: boolean;
|
|
10
|
+
/** The chat app's full name (`SurfaceCaps.name`): what the model reading the request is told. */
|
|
11
|
+
readonly channel: string;
|
|
10
12
|
}
|
|
11
13
|
/** The message with each bare number written as owner/repo#N, the repository read, and what was and was not taken. */
|
|
12
14
|
export interface Expanded {
|
|
@@ -206,6 +206,8 @@ export type ConnectionsText = (connections: WhoamiConnections) => string;
|
|
|
206
206
|
export type ReviewStopReader = (text: string) => readonly (readonly [string, number])[];
|
|
207
207
|
/** What a message to the assistant carries about the chat (the Python `understanding.channel_context`). */
|
|
208
208
|
export interface ChannelContextRequest {
|
|
209
|
+
/** The channel the message came through (`SurfaceCaps.channel`): what Claw is told as `channel`. */
|
|
210
|
+
readonly channel: string;
|
|
209
211
|
readonly channelMessageId: string;
|
|
210
212
|
readonly userId: string;
|
|
211
213
|
readonly message: InboundMessage;
|
|
@@ -45,8 +45,8 @@ export interface TurnRun {
|
|
|
45
45
|
readonly lang: Lang;
|
|
46
46
|
/**
|
|
47
47
|
* The language the turn is to be answered in, told to Claw after the message: in a 1:1 chat the one the person chose (`/lang
|
|
48
|
-
* zh|en`, `chosenLang`), in a group the group's (`groupChosenLang`)
|
|
49
|
-
* of what they wrote. A chat turn's only: a review's follows its request.
|
|
48
|
+
* zh|en`, `chosenLang`), in a group the group's (`groupChosenLang`), or with none the asker's (`AskerLanguages`); undefined:
|
|
49
|
+
* none, and the answer is in the language of what they wrote. A chat turn's only: a review's follows its request.
|
|
50
50
|
*/
|
|
51
51
|
readonly replyLang?: Lang;
|
|
52
52
|
/** The answer gets thumbs of the worker's own (a phone, whose own thumbs never reach the worker). */
|