@skrr-ai/cli 0.1.125 → 0.1.126
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/commands/agents/chat.d.ts +22 -0
- package/dist/commands/agents/chat.js +71 -15
- package/dist/node_modules/@skrr-ai/auth-core/dist/cjs/scheduled-stream-wire.cjs +98 -0
- package/dist/node_modules/@skrr-ai/auth-core/dist/cjs/scheduled-stream-wire.d.cts +15 -0
- package/dist/node_modules/@skrr-ai/auth-core/dist/cjs/telemetryRedaction.js +2 -2
- package/dist/node_modules/@skrr-ai/auth-core/dist/esm/telemetryRedaction.js +2 -2
- package/dist/node_modules/@skrr-ai/auth-core/package.json +4 -0
- package/dist/node_modules/@skrr-ai/data-provider/index.js +8890 -8889
- package/oclif.manifest.json +1 -1
- package/package.json +1 -1
|
@@ -25,6 +25,28 @@ export declare const DETACH_EXIT_CODE = 130;
|
|
|
25
25
|
* answers true.
|
|
26
26
|
*/
|
|
27
27
|
export declare const STREAM_LOST_EXIT_CODE = 75;
|
|
28
|
+
/**
|
|
29
|
+
* The signals that stop a running chat.
|
|
30
|
+
*
|
|
31
|
+
* Ctrl-C was the only one handled (OSK-2938). SIGTERM (a CI cancel, `timeout`, a process manager) and
|
|
32
|
+
* SIGHUP (the terminal closing) killed the CLI in under 100 ms with no cancel sent, so the agent kept
|
|
33
|
+
* running tools on the person's machine with nobody watching and held the folder, and the next message
|
|
34
|
+
* was refused as `managed_task_workspace_busy` (OSK-20677). `machines dedicated cp` already treats all
|
|
35
|
+
* three as cancel and exits as a shell would; this does the same.
|
|
36
|
+
*/
|
|
37
|
+
export declare const INTERRUPT_SIGNALS: readonly ["SIGINT", "SIGTERM", "SIGHUP"];
|
|
38
|
+
export type InterruptSignal = (typeof INTERRUPT_SIGNALS)[number];
|
|
39
|
+
/** 128 plus the signal's number, as a shell reports a process the signal killed: 130, 143, 129. */
|
|
40
|
+
export declare function interruptExitCode(signal: InterruptSignal | null): number;
|
|
41
|
+
/**
|
|
42
|
+
* The cancel notice, in words that fit the signal. "Press Ctrl-C again" is wrong advice after a
|
|
43
|
+
* SIGTERM, and after SIGHUP nobody is looking: the terminal that would show it is gone.
|
|
44
|
+
*/
|
|
45
|
+
export declare function cancelNotice(input: {
|
|
46
|
+
signal: InterruptSignal;
|
|
47
|
+
sessionId: string;
|
|
48
|
+
graceSeconds: number;
|
|
49
|
+
}): string | null;
|
|
28
50
|
/**
|
|
29
51
|
* Exit code for a streamed run that reached its terminal state: 1 when it
|
|
30
52
|
* failed, 0 otherwise.
|
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.MAX_HANDOVER_WAIT_SECONDS = exports.DEFAULT_HANDOVER_WAIT_SECONDS = exports.STREAM_LOST_EXIT_CODE = exports.DETACH_EXIT_CODE = void 0;
|
|
3
|
+
exports.MAX_HANDOVER_WAIT_SECONDS = exports.DEFAULT_HANDOVER_WAIT_SECONDS = exports.INTERRUPT_SIGNALS = exports.STREAM_LOST_EXIT_CODE = exports.DETACH_EXIT_CODE = void 0;
|
|
4
|
+
exports.interruptExitCode = interruptExitCode;
|
|
5
|
+
exports.cancelNotice = cancelNotice;
|
|
4
6
|
exports.streamedResultExitCode = streamedResultExitCode;
|
|
5
7
|
exports.interruptedDetachMessage = interruptedDetachMessage;
|
|
6
8
|
exports.jsonlTextForm = jsonlTextForm;
|
|
@@ -49,6 +51,35 @@ exports.DETACH_EXIT_CODE = 130;
|
|
|
49
51
|
* answers true.
|
|
50
52
|
*/
|
|
51
53
|
exports.STREAM_LOST_EXIT_CODE = 75;
|
|
54
|
+
/**
|
|
55
|
+
* The signals that stop a running chat.
|
|
56
|
+
*
|
|
57
|
+
* Ctrl-C was the only one handled (OSK-2938). SIGTERM (a CI cancel, `timeout`, a process manager) and
|
|
58
|
+
* SIGHUP (the terminal closing) killed the CLI in under 100 ms with no cancel sent, so the agent kept
|
|
59
|
+
* running tools on the person's machine with nobody watching and held the folder, and the next message
|
|
60
|
+
* was refused as `managed_task_workspace_busy` (OSK-20677). `machines dedicated cp` already treats all
|
|
61
|
+
* three as cancel and exits as a shell would; this does the same.
|
|
62
|
+
*/
|
|
63
|
+
exports.INTERRUPT_SIGNALS = ['SIGINT', 'SIGTERM', 'SIGHUP'];
|
|
64
|
+
/** 128 plus the signal's number, as a shell reports a process the signal killed: 130, 143, 129. */
|
|
65
|
+
function interruptExitCode(signal) {
|
|
66
|
+
if (signal === 'SIGTERM')
|
|
67
|
+
return 143;
|
|
68
|
+
if (signal === 'SIGHUP')
|
|
69
|
+
return 129;
|
|
70
|
+
return exports.DETACH_EXIT_CODE;
|
|
71
|
+
}
|
|
72
|
+
/**
|
|
73
|
+
* The cancel notice, in words that fit the signal. "Press Ctrl-C again" is wrong advice after a
|
|
74
|
+
* SIGTERM, and after SIGHUP nobody is looking: the terminal that would show it is gone.
|
|
75
|
+
*/
|
|
76
|
+
function cancelNotice(input) {
|
|
77
|
+
if (input.signal === 'SIGHUP')
|
|
78
|
+
return null;
|
|
79
|
+
const again = input.signal === 'SIGINT' ? 'press Ctrl-C again' : `send ${input.signal} again`;
|
|
80
|
+
return (`\nCancelling run ${input.sessionId}… (waiting up to ${input.graceSeconds}s; ${again} to detach). ` +
|
|
81
|
+
'A tool call already running on the runtime is not guaranteed to stop.');
|
|
82
|
+
}
|
|
52
83
|
/**
|
|
53
84
|
* Exit code for a streamed run that reached its terminal state: 1 when it
|
|
54
85
|
* failed, 0 otherwise.
|
|
@@ -882,10 +913,22 @@ class AgentsChat extends base_command_1.BaseCommand {
|
|
|
882
913
|
detach = () => resolve('detached');
|
|
883
914
|
});
|
|
884
915
|
let interrupts = 0;
|
|
916
|
+
// The signal that started the stop. Its exit status is what a script reads (130, 143 or 129).
|
|
917
|
+
let interruptedBy = null;
|
|
918
|
+
// After SIGHUP the terminal is gone and a write to it throws; the notice is lost, the stop is not.
|
|
919
|
+
const writeNotice = (fd, text) => {
|
|
920
|
+
try {
|
|
921
|
+
(0, node_fs_1.writeSync)(fd, text);
|
|
922
|
+
}
|
|
923
|
+
catch (_error) {
|
|
924
|
+
/* the terminal that would show this is closed */
|
|
925
|
+
}
|
|
926
|
+
};
|
|
885
927
|
let forcedDetachAnnounced = false;
|
|
886
928
|
let graceTimer = null;
|
|
887
|
-
const onInterrupt = () => {
|
|
929
|
+
const onInterrupt = (signal = 'SIGINT') => {
|
|
888
930
|
interrupts += 1;
|
|
931
|
+
interruptedBy ??= signal;
|
|
889
932
|
const action = interruptAction({ interrupts, awaitingHandover: client.awaitingHandover() });
|
|
890
933
|
if (action === 'stop-handover-wait') {
|
|
891
934
|
// Nothing to cancel and nothing to grace-wait for: stop at once.
|
|
@@ -896,7 +939,7 @@ class AgentsChat extends base_command_1.BaseCommand {
|
|
|
896
939
|
conversationId: started.conversationId,
|
|
897
940
|
});
|
|
898
941
|
if (flags.jsonl) {
|
|
899
|
-
(
|
|
942
|
+
writeNotice(process.stdout.fd, `${JSON.stringify({
|
|
900
943
|
type: 'run.detached',
|
|
901
944
|
sessionId: started.sessionId,
|
|
902
945
|
conversationId: started.conversationId,
|
|
@@ -906,9 +949,9 @@ class AgentsChat extends base_command_1.BaseCommand {
|
|
|
906
949
|
})}\n`);
|
|
907
950
|
}
|
|
908
951
|
else {
|
|
909
|
-
(
|
|
952
|
+
writeNotice(process.stderr.fd, `\n${message}\n`);
|
|
910
953
|
}
|
|
911
|
-
process.exitCode =
|
|
954
|
+
process.exitCode = interruptExitCode(interruptedBy);
|
|
912
955
|
}
|
|
913
956
|
client.close();
|
|
914
957
|
detach?.();
|
|
@@ -917,9 +960,13 @@ class AgentsChat extends base_command_1.BaseCommand {
|
|
|
917
960
|
if (action === 'cancel') {
|
|
918
961
|
client.cancel();
|
|
919
962
|
if (!flags.jsonl) {
|
|
920
|
-
|
|
921
|
-
|
|
922
|
-
|
|
963
|
+
const notice = cancelNotice({
|
|
964
|
+
signal,
|
|
965
|
+
sessionId: started.sessionId,
|
|
966
|
+
graceSeconds: CANCEL_GRACE_MS / 1000,
|
|
967
|
+
});
|
|
968
|
+
if (notice)
|
|
969
|
+
writeNotice(process.stdout.fd, `${notice}\n`);
|
|
923
970
|
}
|
|
924
971
|
graceTimer = setTimeout(() => detach?.(), CANCEL_GRACE_MS);
|
|
925
972
|
graceTimer.unref?.();
|
|
@@ -933,7 +980,7 @@ class AgentsChat extends base_command_1.BaseCommand {
|
|
|
933
980
|
forced: true,
|
|
934
981
|
});
|
|
935
982
|
if (flags.jsonl) {
|
|
936
|
-
(
|
|
983
|
+
writeNotice(process.stdout.fd, `${JSON.stringify({
|
|
937
984
|
type: 'run.detached',
|
|
938
985
|
sessionId: started.sessionId,
|
|
939
986
|
conversationId: started.conversationId,
|
|
@@ -942,13 +989,14 @@ class AgentsChat extends base_command_1.BaseCommand {
|
|
|
942
989
|
})}\n`);
|
|
943
990
|
}
|
|
944
991
|
else {
|
|
945
|
-
(
|
|
992
|
+
writeNotice(process.stderr.fd, `\n${message}\n`);
|
|
946
993
|
}
|
|
947
|
-
process.exitCode =
|
|
994
|
+
process.exitCode = interruptExitCode(interruptedBy);
|
|
948
995
|
}
|
|
949
996
|
detach?.();
|
|
950
997
|
};
|
|
951
|
-
|
|
998
|
+
for (const name of exports.INTERRUPT_SIGNALS)
|
|
999
|
+
process.on(name, onInterrupt);
|
|
952
1000
|
try {
|
|
953
1001
|
// OSK-2944 — the run was ACCEPTED before we ever tried to attach. If the
|
|
954
1002
|
// stream cannot be attached, that is a lost view of a live run, not a
|
|
@@ -988,7 +1036,7 @@ class AgentsChat extends base_command_1.BaseCommand {
|
|
|
988
1036
|
// 130 only when a signal actually caused this; otherwise the stream was
|
|
989
1037
|
// lost and claiming SIGINT lies to every script reading the code
|
|
990
1038
|
// (OSK-7660).
|
|
991
|
-
const exit = interrupts > 0 ?
|
|
1039
|
+
const exit = interrupts > 0 ? interruptExitCode(interruptedBy) : exports.STREAM_LOST_EXIT_CODE;
|
|
992
1040
|
if (flags.jsonl) {
|
|
993
1041
|
(0, agentic_stream_1.writeJsonLine)(process.stdout, {
|
|
994
1042
|
type: 'run.detached',
|
|
@@ -1039,15 +1087,23 @@ class AgentsChat extends base_command_1.BaseCommand {
|
|
|
1039
1087
|
this.error(noOutput, { exit: 1 });
|
|
1040
1088
|
this.log(result.text);
|
|
1041
1089
|
}
|
|
1042
|
-
else if (result.status === 'aborted') {
|
|
1090
|
+
else if (result.status === 'aborted' && interruptedBy !== 'SIGHUP') {
|
|
1043
1091
|
// Streaming human mode: say the cancel took, rather than leave the keypress warning last.
|
|
1092
|
+
// (Not after SIGHUP: the terminal that would show it is gone.)
|
|
1044
1093
|
this.log(`\n${cancelledRunMessage({ sessionId: started.sessionId, conversationId: started.conversationId })}`);
|
|
1045
1094
|
}
|
|
1095
|
+
// A run stopped by SIGTERM or SIGHUP ends the way a shell reports a process the signal killed,
|
|
1096
|
+
// so a script can tell a cancelled run from one that finished. Ctrl-C keeps its existing status
|
|
1097
|
+
// (a cancel that took is a success, a detach is 130).
|
|
1098
|
+
if (interruptedBy === 'SIGTERM' || interruptedBy === 'SIGHUP') {
|
|
1099
|
+
process.exitCode = interruptExitCode(interruptedBy);
|
|
1100
|
+
}
|
|
1046
1101
|
}
|
|
1047
1102
|
finally {
|
|
1048
1103
|
if (graceTimer)
|
|
1049
1104
|
clearTimeout(graceTimer);
|
|
1050
|
-
|
|
1105
|
+
for (const name of exports.INTERRUPT_SIGNALS)
|
|
1106
|
+
process.removeListener(name, onInterrupt);
|
|
1051
1107
|
client.close();
|
|
1052
1108
|
}
|
|
1053
1109
|
}
|
|
@@ -0,0 +1,98 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
// Content-addressed source-envelope manifest. A manifest is completeness
|
|
4
|
+
// evidence only after an authenticated native response binds it to its exact
|
|
5
|
+
// dispatch, and every listed envelope has been independently retained.
|
|
6
|
+
const { createHash } = require('node:crypto');
|
|
7
|
+
const MAX_EVENTS = 1024;
|
|
8
|
+
const MAX_EVENT_BYTES = 256 * 1024;
|
|
9
|
+
const MAX_TOTAL_BYTES = 8 * 1024 * 1024;
|
|
10
|
+
const HASH = /^[0-9a-f]{64}$/;
|
|
11
|
+
const id = value => typeof value === 'string' && value.length > 0 && value.length <= 240;
|
|
12
|
+
const digest = value => createHash('sha256').update(value, 'utf8').digest('hex');
|
|
13
|
+
|
|
14
|
+
function sorted(value) {
|
|
15
|
+
if (Array.isArray(value)) return value.map(sorted);
|
|
16
|
+
if (value && typeof value === 'object') return Object.fromEntries(
|
|
17
|
+
Object.keys(value).sort().map(key => [key, sorted(value[key])]));
|
|
18
|
+
return value;
|
|
19
|
+
}
|
|
20
|
+
function normalize(envelope) {
|
|
21
|
+
// JSON round-trip defines the wire representation, rejects cycles, and
|
|
22
|
+
// removes undefined properties in the same way as the uploader.
|
|
23
|
+
const value = JSON.parse(JSON.stringify(envelope));
|
|
24
|
+
if (!value || typeof value !== 'object' || Array.isArray(value) ||
|
|
25
|
+
!id(value.id) || !value.ev || typeof value.ev !== 'object' || Array.isArray(value.ev))
|
|
26
|
+
throw new TypeError('Invalid scheduled stream envelope');
|
|
27
|
+
// These fields are owned by the server or are independently authenticated
|
|
28
|
+
// native receipts, not part of the replayable provider stream.
|
|
29
|
+
for (const key of ['__seq', 'userSeq', '__degraded', 'messageId', 'managedEventType']) delete value[key];
|
|
30
|
+
for (const key of ['autonomousSourceExecutorTerminal', 'autonomousSourceExecutorNotStarted',
|
|
31
|
+
'ordinaryExecutorTerminal', 'personalContextInvocationTerminal', 'personalContextInvocationNotStarted'])
|
|
32
|
+
delete value.ev[key];
|
|
33
|
+
return JSON.stringify(sorted(value));
|
|
34
|
+
}
|
|
35
|
+
function fingerprint(envelope) {
|
|
36
|
+
const json = normalize(envelope);
|
|
37
|
+
const bytes = Buffer.byteLength(json, 'utf8');
|
|
38
|
+
if (bytes > MAX_EVENT_BYTES) throw new RangeError('Scheduled stream envelope exceeds the limit');
|
|
39
|
+
return { hash: digest(json), bytes, json };
|
|
40
|
+
}
|
|
41
|
+
function create(binding) {
|
|
42
|
+
if (!binding || ![binding.runId, binding.sessionId, binding.requestId, binding.dispatchId].every(id))
|
|
43
|
+
throw new TypeError('Invalid scheduled stream binding');
|
|
44
|
+
let closed = false;
|
|
45
|
+
let unavailable = null;
|
|
46
|
+
let totalBytes = 0;
|
|
47
|
+
const hashes = [];
|
|
48
|
+
return {
|
|
49
|
+
add(envelopes) {
|
|
50
|
+
if (closed) throw new Error('Scheduled stream manifest is already closed');
|
|
51
|
+
if (unavailable || !Array.isArray(envelopes)) return;
|
|
52
|
+
for (const envelope of envelopes) {
|
|
53
|
+
if (hashes.length >= MAX_EVENTS) { unavailable = 'event_limit'; break; }
|
|
54
|
+
let entry;
|
|
55
|
+
try { entry = fingerprint(envelope); }
|
|
56
|
+
catch { unavailable = 'invalid_or_oversize_event'; break; }
|
|
57
|
+
if (totalBytes + entry.bytes > MAX_TOTAL_BYTES) { unavailable = 'byte_limit'; break; }
|
|
58
|
+
hashes.push(entry.hash);
|
|
59
|
+
totalBytes += entry.bytes;
|
|
60
|
+
}
|
|
61
|
+
// A partial prefix is never a manifest.
|
|
62
|
+
if (unavailable) { hashes.length = 0; totalBytes = 0; }
|
|
63
|
+
},
|
|
64
|
+
finish() {
|
|
65
|
+
if (closed) throw new Error('Scheduled stream manifest is already closed');
|
|
66
|
+
closed = true;
|
|
67
|
+
if (unavailable) return { unavailable };
|
|
68
|
+
return { manifest: { version: 1, algorithm: 'sha256', runId: binding.runId,
|
|
69
|
+
sessionId: binding.sessionId, requestId: binding.requestId, dispatchId: binding.dispatchId,
|
|
70
|
+
count: hashes.length, totalBytes, hashes: [...hashes] } };
|
|
71
|
+
},
|
|
72
|
+
};
|
|
73
|
+
}
|
|
74
|
+
function validate(manifest, binding) {
|
|
75
|
+
return Boolean(manifest && typeof manifest === 'object' && !Array.isArray(manifest) &&
|
|
76
|
+
Object.keys(manifest).sort().join(',') === 'algorithm,count,dispatchId,hashes,requestId,runId,sessionId,totalBytes,version' &&
|
|
77
|
+
manifest.version === 1 && manifest.algorithm === 'sha256' &&
|
|
78
|
+
['runId', 'sessionId', 'requestId', 'dispatchId'].every(key => id(binding?.[key]) && manifest[key] === binding[key]) &&
|
|
79
|
+
Number.isSafeInteger(manifest.count) && manifest.count >= 0 && manifest.count <= MAX_EVENTS &&
|
|
80
|
+
Number.isSafeInteger(manifest.totalBytes) && manifest.totalBytes >= 0 && manifest.totalBytes <= MAX_TOTAL_BYTES &&
|
|
81
|
+
Array.isArray(manifest.hashes) && manifest.hashes.length === manifest.count &&
|
|
82
|
+
manifest.hashes.every(value => typeof value === 'string' && HASH.test(value)));
|
|
83
|
+
}
|
|
84
|
+
function verify(manifest, binding, envelopes) {
|
|
85
|
+
if (!validate(manifest, binding) || !Array.isArray(envelopes) || envelopes.length !== manifest.count)
|
|
86
|
+
return false;
|
|
87
|
+
let totalBytes = 0;
|
|
88
|
+
try {
|
|
89
|
+
for (let index = 0; index < envelopes.length; index += 1) {
|
|
90
|
+
const entry = fingerprint(envelopes[index]);
|
|
91
|
+
if (entry.hash !== manifest.hashes[index]) return false;
|
|
92
|
+
totalBytes += entry.bytes;
|
|
93
|
+
if (totalBytes > MAX_TOTAL_BYTES) return false;
|
|
94
|
+
}
|
|
95
|
+
} catch { return false; }
|
|
96
|
+
return totalBytes === manifest.totalBytes;
|
|
97
|
+
}
|
|
98
|
+
module.exports = { MAX_EVENTS, MAX_EVENT_BYTES, MAX_TOTAL_BYTES, normalize, fingerprint, create, validate, verify };
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
export interface ScheduledStreamBinding { runId: string; sessionId: string; requestId: string; dispatchId: string }
|
|
2
|
+
export interface ScheduledStreamManifest extends ScheduledStreamBinding {
|
|
3
|
+
version: 1; algorithm: 'sha256'; count: number; totalBytes: number; hashes: string[];
|
|
4
|
+
}
|
|
5
|
+
export const MAX_EVENTS: number;
|
|
6
|
+
export const MAX_EVENT_BYTES: number;
|
|
7
|
+
export const MAX_TOTAL_BYTES: number;
|
|
8
|
+
export function normalize(envelope: unknown): string;
|
|
9
|
+
export function fingerprint(envelope: unknown): { hash: string; bytes: number; json: string };
|
|
10
|
+
export function create(binding: ScheduledStreamBinding): {
|
|
11
|
+
add(envelopes: unknown): void;
|
|
12
|
+
finish(): { manifest: ScheduledStreamManifest } | { unavailable: string };
|
|
13
|
+
};
|
|
14
|
+
export function validate(manifest: unknown, binding: ScheduledStreamBinding): boolean;
|
|
15
|
+
export function verify(manifest: unknown, binding: ScheduledStreamBinding, envelopes: unknown): boolean;
|
|
@@ -34,7 +34,7 @@ const TOKEN_CHAR = "(?:[A-Za-z0-9._-]|%(?:25)*(?:2[DdEe]|3[0-9]|4[1-9A-Fa-f]|5[0
|
|
|
34
34
|
const PREVIEW_TOKEN = new RegExp(`pvw(?:_|%(?:25)*5[Ff])${TOKEN_CHAR}+`, "g");
|
|
35
35
|
const UNDERSCORE = "(?:_|%(?:25)*5[Ff])";
|
|
36
36
|
const DOT = "(?:\\.|%(?:25)*2[Ee])";
|
|
37
|
-
const SIGNED_CREDENTIAL = new RegExp(`(wsi|pinv|usr|adm2)${UNDERSCORE}(?=[0-9a-f]{32}${DOT})${TOKEN_CHAR}+`, "g");
|
|
37
|
+
const SIGNED_CREDENTIAL = new RegExp(`(wsi|pinv|iinv|usr|adm2)${UNDERSCORE}(?=[0-9a-f]{32}${DOT})${TOKEN_CHAR}+`, "g");
|
|
38
38
|
const LEGACY_OPERATOR_CODE = new RegExp(`(adm)${UNDERSCORE}(?=[A-Za-z0-9_-]{43}(?![A-Za-z0-9_-]))[A-Za-z0-9_-]{43}`, "g");
|
|
39
39
|
const QR_SIGN_IN_REDACTION = "[redacted]";
|
|
40
40
|
const escapedLiteral = (value) => [...value].map((char) => {
|
|
@@ -72,7 +72,7 @@ function redactQrSignInText(value) {
|
|
|
72
72
|
const standaloneQuery = /(?:^|[?&])direction=(?:mobile_approves_web|web_approves_mobile)(?:&|$)/.test(value) ? value.replace(QR_REQUEST_QUERY, `$1$2${QR_SIGN_IN_REDACTION}`) : value;
|
|
73
73
|
return standaloneQuery.replace(QR_REQUEST_PATH, `$1${QR_SIGN_IN_REDACTION}`).replace(QR_LINK_QUERY, (_match, prefix, query) => prefix + query.replace(QR_REQUEST_QUERY, `$1$2${QR_SIGN_IN_REDACTION}`)).replace(QR_SECRET_ASSIGNMENT, `$1${QR_SIGN_IN_REDACTION}`);
|
|
74
74
|
}
|
|
75
|
-
const CREDENTIAL_HINTS = ["pvw", "wsi", "pinv", "usr", "adm"];
|
|
75
|
+
const CREDENTIAL_HINTS = ["pvw", "wsi", "pinv", "iinv", "usr", "adm"];
|
|
76
76
|
const credentialMarker = (_match, prefix) => `${prefix}_[redacted]`;
|
|
77
77
|
function redactPreviewTokens(value) {
|
|
78
78
|
if (typeof value !== "string")
|
|
@@ -82,7 +82,7 @@ const DOT = '(?:\\.|%(?:25)*2[Ee])';
|
|
|
82
82
|
* prefix is captured so the marker can say which kind it was. `usr_<40 hex>`, `usr_00000001` and `/usr_profile` have no
|
|
83
83
|
* dot after exactly 32 hex characters, so they match nothing.
|
|
84
84
|
*/
|
|
85
|
-
const SIGNED_CREDENTIAL = new RegExp(`(wsi|pinv|usr|adm2)${UNDERSCORE}(?=[0-9a-f]{32}${DOT})${TOKEN_CHAR}+`, 'g');
|
|
85
|
+
const SIGNED_CREDENTIAL = new RegExp(`(wsi|pinv|iinv|usr|adm2)${UNDERSCORE}(?=[0-9a-f]{32}${DOT})${TOKEN_CHAR}+`, 'g');
|
|
86
86
|
/**
|
|
87
87
|
* The older operator code: `adm_` and exactly 43 base64url characters (32 random bytes), not followed by another one.
|
|
88
88
|
* A shorter or longer run of letters is a name, not this credential. The characters are the plain alphabet and not
|
|
@@ -134,7 +134,7 @@ function redactQrSignInText(value) {
|
|
|
134
134
|
.replace(QR_SECRET_ASSIGNMENT, `$1${QR_SIGN_IN_REDACTION}`);
|
|
135
135
|
}
|
|
136
136
|
/** Cheap test before the older prefix-based credential expressions. */
|
|
137
|
-
const CREDENTIAL_HINTS = ['pvw', 'wsi', 'pinv', 'usr', 'adm'];
|
|
137
|
+
const CREDENTIAL_HINTS = ['pvw', 'wsi', 'pinv', 'iinv', 'usr', 'adm'];
|
|
138
138
|
const credentialMarker = (_match, prefix) => `${prefix}_[redacted]`;
|
|
139
139
|
export function redactPreviewTokens(value) {
|
|
140
140
|
if (typeof value !== 'string')
|
|
@@ -4,6 +4,10 @@
|
|
|
4
4
|
"main": "dist/cjs/index.js",
|
|
5
5
|
"types": "dist/esm/index.d.ts",
|
|
6
6
|
"exports": {
|
|
7
|
+
"./scheduled-stream-wire": {
|
|
8
|
+
"types": "./dist/cjs/scheduled-stream-wire.d.cts",
|
|
9
|
+
"default": "./dist/cjs/scheduled-stream-wire.cjs"
|
|
10
|
+
},
|
|
7
11
|
"./desktop-daemon-proof": {
|
|
8
12
|
"import": {
|
|
9
13
|
"types": "./dist/esm/desktopDaemonProof.d.ts",
|