@primusclaw/personal-agent-runtime 0.1.1 → 0.2.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 +111 -19
- package/dist/sqlite/schema.sql +2 -0
- package/dist/types/claw/identity-lookup.d.ts +25 -7
- package/dist/types/claw/index.d.ts +1 -1
- package/dist/types/claw/remote-agents.d.ts +2 -0
- package/dist/types/config/settings.d.ts +2 -0
- package/dist/types/sqlite/group-context-repository.d.ts +9 -0
- package/dist/types/sqlite/remote-repository.d.ts +2 -0
- package/dist/types/sqlite/store.d.ts +2 -0
- package/package.json +2 -2
package/dist/index.js
CHANGED
|
@@ -529,6 +529,12 @@ var Watchdog = class {
|
|
|
529
529
|
};
|
|
530
530
|
|
|
531
531
|
// packages/runtime/src/claw/remote-agents.ts
|
|
532
|
+
function enabledOf(answer2) {
|
|
533
|
+
const data = anyDataOf(answer2, "the approvals setting");
|
|
534
|
+
const enabled = data !== null && typeof data === "object" ? data["enabled"] : void 0;
|
|
535
|
+
if (typeof enabled !== "boolean") throw new ClawAnswerInvalid4("the approvals setting has no enabled");
|
|
536
|
+
return enabled;
|
|
537
|
+
}
|
|
532
538
|
var HttpRemoteAgents = class {
|
|
533
539
|
constructor(http, clientLabel) {
|
|
534
540
|
this.http = http;
|
|
@@ -543,6 +549,12 @@ var HttpRemoteAgents = class {
|
|
|
543
549
|
const path = options.includeHidden === true ? `/connectors?hidden=${REMOTE_HIDDEN_INCLUDE}` : "/connectors";
|
|
544
550
|
return read(remoteConnectorsSchema, anyDataOf(await this.#call("GET", path, key2), "connectors"), "connectors");
|
|
545
551
|
}
|
|
552
|
+
async approvals(key2) {
|
|
553
|
+
return enabledOf(await this.#call("GET", "/approvals", key2));
|
|
554
|
+
}
|
|
555
|
+
async setApprovals(key2, enabled) {
|
|
556
|
+
return enabledOf(await this.#call("PUT", "/approvals", key2, { enabled }));
|
|
557
|
+
}
|
|
546
558
|
async pair(key2) {
|
|
547
559
|
return read(
|
|
548
560
|
remotePairingSchema,
|
|
@@ -1233,6 +1245,7 @@ function createClawClient(options) {
|
|
|
1233
1245
|
// packages/runtime/src/claw/identity-lookup.ts
|
|
1234
1246
|
import {
|
|
1235
1247
|
ClawUnreachable as ClawUnreachable3,
|
|
1248
|
+
isApiKey as isApiKey3,
|
|
1236
1249
|
pyLower,
|
|
1237
1250
|
pyStrip as pyStrip3,
|
|
1238
1251
|
pyStrOf as pyStrOf3,
|
|
@@ -1240,19 +1253,33 @@ import {
|
|
|
1240
1253
|
} from "@primusclaw/personal-agent";
|
|
1241
1254
|
var HttpIdentityLookup = class {
|
|
1242
1255
|
/** `safeApiUrl` is the platform API without a trailing slash (Settings.safeApiUrl). */
|
|
1243
|
-
constructor(safeApiUrl, fetchImpl = fetch, timeoutMs = DEFAULT_TIMEOUT_MS) {
|
|
1256
|
+
constructor(safeApiUrl, fetchImpl = fetch, timeoutMs = DEFAULT_TIMEOUT_MS, options = {}) {
|
|
1244
1257
|
this.timeoutMs = timeoutMs;
|
|
1245
|
-
this.
|
|
1258
|
+
this.safe = new ClawHttp(safeApiUrl, fetchImpl);
|
|
1259
|
+
this.claw = options.clawApiUrl ? new ClawHttp(options.clawApiUrl, fetchImpl) : void 0;
|
|
1260
|
+
this.logger = options.logger;
|
|
1246
1261
|
}
|
|
1247
1262
|
timeoutMs;
|
|
1248
|
-
|
|
1263
|
+
safe;
|
|
1264
|
+
claw;
|
|
1265
|
+
logger;
|
|
1249
1266
|
async ownerOfKey(key2) {
|
|
1250
|
-
|
|
1267
|
+
if (isApiKey3(key2)) {
|
|
1268
|
+
const body2 = await this.ask(this.safe, "/users/self", key2, "api_key");
|
|
1269
|
+
return body2 === void 0 ? void 0 : ownerIn(body2);
|
|
1270
|
+
}
|
|
1271
|
+
if (this.claw === void 0) return void 0;
|
|
1272
|
+
const body = await this.ask(this.claw, "/v1/me", key2, "identity_token");
|
|
1273
|
+
return body === void 0 ? void 0 : ownerInMe(body);
|
|
1274
|
+
}
|
|
1275
|
+
/** The JSON answer of `GET what` asked with `key`; undefined on any failure. */
|
|
1276
|
+
async ask(http, what, key2, kind) {
|
|
1251
1277
|
let text3;
|
|
1252
1278
|
try {
|
|
1253
|
-
const response = await
|
|
1279
|
+
const response = await http.send({ method: "GET", path: what, key: key2, timeoutMs: this.timeoutMs });
|
|
1254
1280
|
if (response.status !== 200) {
|
|
1255
1281
|
await response.body?.cancel();
|
|
1282
|
+
this.logger?.info("identity lookup: no owner", { route: what, status: response.status, credential: kind });
|
|
1256
1283
|
return void 0;
|
|
1257
1284
|
}
|
|
1258
1285
|
text3 = await readText(response, what);
|
|
@@ -1260,13 +1287,11 @@ var HttpIdentityLookup = class {
|
|
|
1260
1287
|
if (err5 instanceof ClawUnreachable3) return void 0;
|
|
1261
1288
|
throw err5;
|
|
1262
1289
|
}
|
|
1263
|
-
let body;
|
|
1264
1290
|
try {
|
|
1265
|
-
|
|
1291
|
+
return JSON.parse(text3);
|
|
1266
1292
|
} catch {
|
|
1267
1293
|
return void 0;
|
|
1268
1294
|
}
|
|
1269
|
-
return ownerIn(body);
|
|
1270
1295
|
}
|
|
1271
1296
|
};
|
|
1272
1297
|
function field(user, name) {
|
|
@@ -1285,6 +1310,10 @@ function ownerIn(body) {
|
|
|
1285
1310
|
accountType: pyLower(field(user, "type"))
|
|
1286
1311
|
};
|
|
1287
1312
|
}
|
|
1313
|
+
function ownerInMe(body) {
|
|
1314
|
+
if (!isObject5(body)) return void 0;
|
|
1315
|
+
return { id: field(body, "userId"), name: field(body, "name"), email: field(body, "email"), accountType: "" };
|
|
1316
|
+
}
|
|
1288
1317
|
|
|
1289
1318
|
// packages/runtime/src/claw/key-revoker.ts
|
|
1290
1319
|
import { ClawUnreachable as ClawUnreachable4, pyTruthy as pyTruthy5 } from "@primusclaw/personal-agent";
|
|
@@ -1935,11 +1964,13 @@ import {
|
|
|
1935
1964
|
DEFAULT_MAX_CONCURRENT_TASKS,
|
|
1936
1965
|
DEFAULT_MESSAGE_LIMIT,
|
|
1937
1966
|
DEFAULT_MESSAGE_WINDOW_SECONDS,
|
|
1967
|
+
DEFAULT_GROUP_CONTEXT,
|
|
1938
1968
|
decimalBigInt as decimalBigInt2,
|
|
1939
1969
|
parseLimits
|
|
1940
1970
|
} from "@primusclaw/personal-agent";
|
|
1941
1971
|
var GITHUB_CLI_CLIENT_ID = "178c6fc778ccc68e1d6a";
|
|
1942
1972
|
var ASSISTANT_REPLY_WINDOW_SECONDS = 30 * 60;
|
|
1973
|
+
var MAX_GROUP_CONTEXT_MESSAGES = 200;
|
|
1943
1974
|
function readSettings(env, secrets = /* @__PURE__ */ new Map()) {
|
|
1944
1975
|
const read2 = new EnvReader(env);
|
|
1945
1976
|
const store = { values: secrets, source: secretsSourceOf(env) };
|
|
@@ -1975,6 +2006,7 @@ function readSettings(env, secrets = /* @__PURE__ */ new Map()) {
|
|
|
1975
2006
|
directChat: directChat(read2),
|
|
1976
2007
|
onBehalfUsers: new Set(read2.list("TEAMS_ON_BEHALF_USERS")),
|
|
1977
2008
|
observeUsers: new Set(read2.list("TEAMS_OBSERVE_USERS", true)),
|
|
2009
|
+
groupContext: groupContextSettings(read2),
|
|
1978
2010
|
sensitiveLimits: limitsOf(read2),
|
|
1979
2011
|
linkLimits: {
|
|
1980
2012
|
perUser: read2.positiveInt("TEAMS_LINK_MAX_FAILURES_PER_USER", 5),
|
|
@@ -1989,6 +2021,19 @@ function readSettings(env, secrets = /* @__PURE__ */ new Map()) {
|
|
|
1989
2021
|
secretsSource: store.source
|
|
1990
2022
|
};
|
|
1991
2023
|
}
|
|
2024
|
+
function groupContextSettings(read2) {
|
|
2025
|
+
const messages = read2.int("TEAMS_GROUP_CONTEXT_MESSAGES", String(DEFAULT_GROUP_CONTEXT.messages));
|
|
2026
|
+
if (messages < 0 || messages > MAX_GROUP_CONTEXT_MESSAGES) {
|
|
2027
|
+
throw new ConfigError2(
|
|
2028
|
+
`TEAMS_GROUP_CONTEXT_MESSAGES must be between 0 and ${String(MAX_GROUP_CONTEXT_MESSAGES)}, not ${String(messages)}`
|
|
2029
|
+
);
|
|
2030
|
+
}
|
|
2031
|
+
return {
|
|
2032
|
+
messages,
|
|
2033
|
+
maxAgeSeconds: read2.positiveInt("TEAMS_GROUP_CONTEXT_HOURS", DEFAULT_GROUP_CONTEXT.maxAgeSeconds / 3600) * 3600,
|
|
2034
|
+
messageChars: read2.positiveInt("TEAMS_GROUP_CONTEXT_CHARS", DEFAULT_GROUP_CONTEXT.messageChars)
|
|
2035
|
+
};
|
|
2036
|
+
}
|
|
1992
2037
|
function secret(read2, store, name) {
|
|
1993
2038
|
const loaded = store.values.get(name);
|
|
1994
2039
|
if (loaded !== void 0) return loaded;
|
|
@@ -3608,6 +3653,15 @@ var ADDED_COLUMNS = [
|
|
|
3608
3653
|
]
|
|
3609
3654
|
],
|
|
3610
3655
|
["notify_subs", [["types_version", "INTEGER NOT NULL DEFAULT 0"]]],
|
|
3656
|
+
[
|
|
3657
|
+
"remote_permissions",
|
|
3658
|
+
[
|
|
3659
|
+
["message_id", "TEXT NOT NULL DEFAULT ''"],
|
|
3660
|
+
// '' = the channel never said the card's id
|
|
3661
|
+
["ask_json", "TEXT NOT NULL DEFAULT ''"]
|
|
3662
|
+
// '' = not a question a terminal asks
|
|
3663
|
+
]
|
|
3664
|
+
],
|
|
3611
3665
|
[
|
|
3612
3666
|
"turn_answers",
|
|
3613
3667
|
[
|
|
@@ -3841,6 +3895,26 @@ var SqliteObserveRepository = class {
|
|
|
3841
3895
|
}
|
|
3842
3896
|
};
|
|
3843
3897
|
|
|
3898
|
+
// packages/runtime/src/sqlite/group-context-repository.ts
|
|
3899
|
+
var SqliteGroupContextRepository = class {
|
|
3900
|
+
constructor(ctx) {
|
|
3901
|
+
this.ctx = ctx;
|
|
3902
|
+
}
|
|
3903
|
+
ctx;
|
|
3904
|
+
contextOff(conversationId) {
|
|
3905
|
+
return this.ctx.db.get("SELECT 1 AS off FROM group_context_off WHERE conversation_id = ?", conversationId) !== void 0;
|
|
3906
|
+
}
|
|
3907
|
+
setContextOff(conversationId, off) {
|
|
3908
|
+
if (off) {
|
|
3909
|
+
this.ctx.db.run(
|
|
3910
|
+
"INSERT INTO group_context_off (conversation_id, updated_at) VALUES (?, ?) ON CONFLICT (conversation_id) DO UPDATE SET updated_at = excluded.updated_at",
|
|
3911
|
+
conversationId,
|
|
3912
|
+
this.ctx.now()
|
|
3913
|
+
);
|
|
3914
|
+
} else this.ctx.db.run("DELETE FROM group_context_off WHERE conversation_id = ?", conversationId);
|
|
3915
|
+
}
|
|
3916
|
+
};
|
|
3917
|
+
|
|
3844
3918
|
// packages/runtime/src/sqlite/people-repository.ts
|
|
3845
3919
|
import {
|
|
3846
3920
|
DEFAULT_QUIET,
|
|
@@ -4044,7 +4118,7 @@ var SqliteRemoteSessionNameRepository = class {
|
|
|
4044
4118
|
);
|
|
4045
4119
|
}
|
|
4046
4120
|
};
|
|
4047
|
-
var PERMISSION_COLUMNS = "session_id, action_id, aad_id, tool, options_json, expires_at, state";
|
|
4121
|
+
var PERMISSION_COLUMNS = "session_id, action_id, aad_id, tool, options_json, expires_at, state, message_id, ask_json";
|
|
4048
4122
|
function permission(row) {
|
|
4049
4123
|
return {
|
|
4050
4124
|
sessionId: col.str(row, "session_id"),
|
|
@@ -4053,9 +4127,20 @@ function permission(row) {
|
|
|
4053
4127
|
tool: col.str(row, "tool"),
|
|
4054
4128
|
options: jsonList(col.str(row, "options_json")),
|
|
4055
4129
|
expiresAt: col.num(row, "expires_at"),
|
|
4056
|
-
state: col.str(row, "state")
|
|
4130
|
+
state: col.str(row, "state"),
|
|
4131
|
+
messageId: col.str(row, "message_id"),
|
|
4132
|
+
ask: askOf(col.str(row, "ask_json"))
|
|
4057
4133
|
};
|
|
4058
4134
|
}
|
|
4135
|
+
function askOf(text3) {
|
|
4136
|
+
if (!text3) return null;
|
|
4137
|
+
try {
|
|
4138
|
+
const value = JSON.parse(text3);
|
|
4139
|
+
return value !== null && typeof value === "object" && !Array.isArray(value) ? value : null;
|
|
4140
|
+
} catch {
|
|
4141
|
+
return null;
|
|
4142
|
+
}
|
|
4143
|
+
}
|
|
4059
4144
|
var SqliteRemotePermissionRepository = class {
|
|
4060
4145
|
constructor(ctx) {
|
|
4061
4146
|
this.ctx = ctx;
|
|
@@ -4065,14 +4150,15 @@ var SqliteRemotePermissionRepository = class {
|
|
|
4065
4150
|
const now = this.ctx.now();
|
|
4066
4151
|
this.ctx.db.run("DELETE FROM remote_permissions WHERE expires_at < ?", now - REMOTE_PERMISSION_KEEP_SECONDS);
|
|
4067
4152
|
return this.ctx.db.run(
|
|
4068
|
-
"INSERT OR IGNORE INTO remote_permissions (session_id, action_id, aad_id, tool, options_json, expires_at, created_at) VALUES (?, ?, ?, ?, ?, ?, ?)",
|
|
4153
|
+
"INSERT OR IGNORE INTO remote_permissions (session_id, action_id, aad_id, tool, options_json, expires_at, created_at, ask_json) VALUES (?, ?, ?, ?, ?, ?, ?, ?)",
|
|
4069
4154
|
p.sessionId,
|
|
4070
4155
|
p.actionId,
|
|
4071
4156
|
p.userId,
|
|
4072
4157
|
p.tool,
|
|
4073
4158
|
pyJsonDumps(p.options),
|
|
4074
4159
|
p.expiresAt,
|
|
4075
|
-
now
|
|
4160
|
+
now,
|
|
4161
|
+
p.ask ? JSON.stringify(p.ask) : ""
|
|
4076
4162
|
) === 1;
|
|
4077
4163
|
}
|
|
4078
4164
|
getRemotePermission(sessionId, actionId) {
|
|
@@ -4099,17 +4185,21 @@ var SqliteRemotePermissionRepository = class {
|
|
|
4099
4185
|
);
|
|
4100
4186
|
return new Set(rows.map((r) => col.str(r, "session_id")));
|
|
4101
4187
|
}
|
|
4188
|
+
setRemotePermissionMessage(sessionId, actionId, messageId) {
|
|
4189
|
+
this.ctx.db.run(
|
|
4190
|
+
"UPDATE remote_permissions SET message_id = ? WHERE session_id = ? AND action_id = ?",
|
|
4191
|
+
messageId,
|
|
4192
|
+
sessionId,
|
|
4193
|
+
actionId
|
|
4194
|
+
);
|
|
4195
|
+
}
|
|
4102
4196
|
forgetRemotePermission(sessionId, actionId) {
|
|
4103
4197
|
this.ctx.db.run("DELETE FROM remote_permissions WHERE session_id = ? AND action_id = ?", sessionId, actionId);
|
|
4104
4198
|
}
|
|
4105
4199
|
closeRemotePermission(sessionId, actionId, state, options = {}) {
|
|
4106
|
-
const
|
|
4107
|
-
|
|
4108
|
-
|
|
4109
|
-
state,
|
|
4110
|
-
sessionId,
|
|
4111
|
-
actionId
|
|
4112
|
-
) === 1;
|
|
4200
|
+
const from = options.onlyIfState ?? (options.onlyIfPending ?? true ? "pending" : null);
|
|
4201
|
+
const sql = "UPDATE remote_permissions SET state = ? WHERE session_id = ? AND action_id = ?";
|
|
4202
|
+
return from === null ? this.ctx.db.run(sql, state, sessionId, actionId) === 1 : this.ctx.db.run(`${sql} AND state = ?`, state, sessionId, actionId, from) === 1;
|
|
4113
4203
|
}
|
|
4114
4204
|
};
|
|
4115
4205
|
|
|
@@ -4499,6 +4589,7 @@ var SqliteStore = class {
|
|
|
4499
4589
|
notifySubs;
|
|
4500
4590
|
approvals;
|
|
4501
4591
|
observe;
|
|
4592
|
+
groupContext;
|
|
4502
4593
|
assistantCards;
|
|
4503
4594
|
assistantButtons;
|
|
4504
4595
|
assistantMessages;
|
|
@@ -4530,6 +4621,7 @@ var SqliteStore = class {
|
|
|
4530
4621
|
this.notifySubs = new SqliteNotifySubscriptionRepository(ctx);
|
|
4531
4622
|
this.approvals = new SqliteApprovalRepository(ctx);
|
|
4532
4623
|
this.observe = new SqliteObserveRepository(ctx);
|
|
4624
|
+
this.groupContext = new SqliteGroupContextRepository(ctx);
|
|
4533
4625
|
this.assistantCards = new SqliteAssistantCardRepository(ctx);
|
|
4534
4626
|
this.assistantButtons = new SqliteAssistantButtonRepository(ctx);
|
|
4535
4627
|
this.assistantMessages = new SqliteAssistantMessageRepository(ctx);
|
package/dist/sqlite/schema.sql
CHANGED
|
@@ -120,3 +120,5 @@ CREATE TABLE IF NOT EXISTS observe_cards (
|
|
|
120
120
|
tool TEXT NOT NULL, args TEXT NOT NULL, message TEXT NOT NULL DEFAULT '', state TEXT NOT NULL DEFAULT 'open',
|
|
121
121
|
created_at REAL NOT NULL);
|
|
122
122
|
CREATE INDEX IF NOT EXISTS observe_cards_by_suggestion ON observe_cards (aad_id, run_id, seq);
|
|
123
|
+
CREATE TABLE IF NOT EXISTS group_context_off (
|
|
124
|
+
conversation_id TEXT PRIMARY KEY, updated_at REAL NOT NULL);
|
|
@@ -1,15 +1,33 @@
|
|
|
1
|
-
import { type IdentityLookup, type KeyOwner } from "@primusclaw/personal-agent";
|
|
1
|
+
import { type IdentityLookup, type KeyOwner, type Logger } from "@primusclaw/personal-agent";
|
|
2
2
|
import { type Fetch } from "./http.js";
|
|
3
|
+
/** Where a lookup asks besides the platform, and where it says that an answer was not 200. */
|
|
4
|
+
export interface IdentityLookupOptions {
|
|
5
|
+
/**
|
|
6
|
+
* Claw's API without a trailing slash (Settings.clawApiUrl). An exchanged identity token is asked about here, at
|
|
7
|
+
* `GET /v1/me`: it is a token for Claw's audience, which the platform's `/users/self` refuses (401). Without it a
|
|
8
|
+
* token has no owner.
|
|
9
|
+
*/
|
|
10
|
+
readonly clawApiUrl?: string;
|
|
11
|
+
/** Where an answer other than 200 is noted: its status, the route and the kind of credential, never the credential. */
|
|
12
|
+
readonly logger?: Logger;
|
|
13
|
+
}
|
|
3
14
|
/**
|
|
4
|
-
* Who a
|
|
5
|
-
* `safe.safe_user` and `safe.user_id_of`, which read the same answer).
|
|
6
|
-
*
|
|
7
|
-
*
|
|
15
|
+
* Who a credential belongs to. A person's own key (`ak-...`) is asked of the platform's `/users/self` with the key itself
|
|
16
|
+
* (the Python worker's `safe.whoami`, `safe.safe_user` and `safe.user_id_of`, which read the same answer). An identity
|
|
17
|
+
* token exchanged for them (TEAMS_EXCHANGE_FOR_CHAT) is asked of Claw's `/v1/me` with the token, when Claw's URL is
|
|
18
|
+
* given: the platform does not take such a token on its data routes, and Claw answers with the platform's id, name and
|
|
19
|
+
* email of the token's subject (it has no account type: ""). Any failure is no owner: an answer other than 200, a timeout
|
|
20
|
+
* or a broken connection, a body that is not JSON or not an object. The caller says so, or tries again later (the
|
|
21
|
+
* subscriptions' timer that fills in Claw user ids).
|
|
8
22
|
*/
|
|
9
23
|
export declare class HttpIdentityLookup implements IdentityLookup {
|
|
10
24
|
private readonly timeoutMs;
|
|
11
|
-
private readonly
|
|
25
|
+
private readonly safe;
|
|
26
|
+
private readonly claw;
|
|
27
|
+
private readonly logger;
|
|
12
28
|
/** `safeApiUrl` is the platform API without a trailing slash (Settings.safeApiUrl). */
|
|
13
|
-
constructor(safeApiUrl: string, fetchImpl?: Fetch, timeoutMs?: number);
|
|
29
|
+
constructor(safeApiUrl: string, fetchImpl?: Fetch, timeoutMs?: number, options?: IdentityLookupOptions);
|
|
14
30
|
ownerOfKey(key: string): Promise<KeyOwner | undefined>;
|
|
31
|
+
/** The JSON answer of `GET what` asked with `key`; undefined on any failure. */
|
|
32
|
+
private ask;
|
|
15
33
|
}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
export { createClawClient, DEFAULT_CLIENT_LABEL, type ClawClientOptions } from "./client.js";
|
|
2
2
|
export type { Fetch } from "./http.js";
|
|
3
|
-
export { HttpIdentityLookup } from "./identity-lookup.js";
|
|
3
|
+
export { HttpIdentityLookup, type IdentityLookupOptions } from "./identity-lookup.js";
|
|
4
4
|
export { HttpKeyRevoker } from "./key-revoker.js";
|
|
5
5
|
export { ruleText } from "./rule.js";
|
|
@@ -10,6 +10,8 @@ export declare class HttpRemoteAgents implements ClawRemoteAgentsPort {
|
|
|
10
10
|
connectors(key: ClawCredential, options?: {
|
|
11
11
|
includeHidden?: boolean;
|
|
12
12
|
}): Promise<RemoteConnector[]>;
|
|
13
|
+
approvals(key: ClawCredential): Promise<boolean>;
|
|
14
|
+
setApprovals(key: ClawCredential, enabled: boolean): Promise<boolean>;
|
|
13
15
|
pair(key: ClawCredential): Promise<RemotePairing>;
|
|
14
16
|
hide(key: ClawCredential, connectorId: string, refs: readonly string[], hidden: boolean): Promise<RemoteHidden>;
|
|
15
17
|
revoke(key: ClawCredential, connectorId: string): Promise<void>;
|
|
@@ -4,6 +4,8 @@ import { type Env } from "./env.js";
|
|
|
4
4
|
export declare const GITHUB_CLI_CLIENT_ID = "178c6fc778ccc68e1d6a";
|
|
5
5
|
/** The default of ASSISTANT_REPLY_WINDOW_SECONDS. */
|
|
6
6
|
export declare const ASSISTANT_REPLY_WINDOW_SECONDS: number;
|
|
7
|
+
/** The most messages TEAMS_GROUP_CONTEXT_MESSAGES may keep per group chat. */
|
|
8
|
+
export declare const MAX_GROUP_CONTEXT_MESSAGES = 200;
|
|
7
9
|
/**
|
|
8
10
|
* The worker's channel-neutral settings from the environment (the Python worker's `Settings.from_env`, without the
|
|
9
11
|
* Teams fields). `secrets` are what the deployment's SecretSource loaded; a name it holds is taken from there and never
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
/** GroupContextRepository on SQLite (table `group_context_off`: one row per chat that turned the context off). */
|
|
2
|
+
import type { GroupContextRepository } from "@primusclaw/personal-agent";
|
|
3
|
+
import type { StoreContext } from "./context.js";
|
|
4
|
+
export declare class SqliteGroupContextRepository implements GroupContextRepository {
|
|
5
|
+
private readonly ctx;
|
|
6
|
+
constructor(ctx: StoreContext);
|
|
7
|
+
contextOff(conversationId: string): boolean;
|
|
8
|
+
setContextOff(conversationId: string, off: boolean): void;
|
|
9
|
+
}
|
|
@@ -17,8 +17,10 @@ export declare class SqliteRemotePermissionRepository implements RemotePermissio
|
|
|
17
17
|
getRemotePermission(sessionId: string, actionId: string): RemotePermission | null;
|
|
18
18
|
pendingRemotePermissions(userId: string, sessionId: string): RemotePermission[];
|
|
19
19
|
waitingRemoteSessions(userId: string): Set<string>;
|
|
20
|
+
setRemotePermissionMessage(sessionId: string, actionId: string, messageId: string): void;
|
|
20
21
|
forgetRemotePermission(sessionId: string, actionId: string): void;
|
|
21
22
|
closeRemotePermission(sessionId: string, actionId: string, state: RemotePermissionState, options?: {
|
|
22
23
|
readonly onlyIfPending?: boolean;
|
|
24
|
+
readonly onlyIfState?: RemotePermissionState;
|
|
23
25
|
}): boolean;
|
|
24
26
|
}
|
|
@@ -13,6 +13,7 @@ import { SqliteLinkRepository } from "./link-repository.js";
|
|
|
13
13
|
import { SqliteMemberDirectoryRepository } from "./member-repository.js";
|
|
14
14
|
import { SqliteNotifySubscriptionRepository } from "./notify-repository.js";
|
|
15
15
|
import { SqliteObserveRepository } from "./observe-repository.js";
|
|
16
|
+
import { SqliteGroupContextRepository } from "./group-context-repository.js";
|
|
16
17
|
import { SqliteOnboardingRepository } from "./onboarding-repository.js";
|
|
17
18
|
import { SqliteConversationRefRepository, SqliteHeldEventRepository, SqlitePrefsRepository } from "./people-repository.js";
|
|
18
19
|
import { type ReencryptCounts } from "./reencrypt.js";
|
|
@@ -45,6 +46,7 @@ export declare class SqliteStore implements StorePort {
|
|
|
45
46
|
readonly notifySubs: SqliteNotifySubscriptionRepository;
|
|
46
47
|
readonly approvals: SqliteApprovalRepository;
|
|
47
48
|
readonly observe: SqliteObserveRepository;
|
|
49
|
+
readonly groupContext: SqliteGroupContextRepository;
|
|
48
50
|
readonly assistantCards: SqliteAssistantCardRepository;
|
|
49
51
|
readonly assistantButtons: SqliteAssistantButtonRepository;
|
|
50
52
|
readonly assistantMessages: SqliteAssistantMessageRepository;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@primusclaw/personal-agent-runtime",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.2.0",
|
|
4
4
|
"description": "Node adapters for the personal agent's ports: clock, randomness, logging (and, as the port lands, storage, Claw, metrics, HTTP).",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"repository": {
|
|
@@ -29,7 +29,7 @@
|
|
|
29
29
|
"access": "public"
|
|
30
30
|
},
|
|
31
31
|
"dependencies": {
|
|
32
|
-
"@primusclaw/personal-agent": "0.
|
|
32
|
+
"@primusclaw/personal-agent": "0.2.0",
|
|
33
33
|
"fastify": "^5.12.8",
|
|
34
34
|
"zod": "^4.6.7"
|
|
35
35
|
}
|