harnery 0.45.2 → 0.46.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/commander.d.ts +13 -0
- package/dist/commander.d.ts.map +1 -1
- package/dist/commands/admission.d.ts.map +1 -1
- package/dist/commands/admission.js +214 -27
- package/dist/commands/agents.d.ts +4 -0
- package/dist/commands/agents.d.ts.map +1 -1
- package/dist/commands/agents.js +102 -25
- package/dist/commands/browse.d.ts +3 -0
- package/dist/commands/browse.d.ts.map +1 -1
- package/dist/commands/browse.js +172 -8
- package/dist/commands/fetch.js +1 -0
- package/dist/commands/ledger-v3.d.ts.map +1 -1
- package/dist/commands/ledger-v3.js +8 -2
- package/dist/commands/presence.d.ts.map +1 -1
- package/dist/commands/presence.js +40 -0
- package/dist/commands/qa-run.d.ts.map +1 -1
- package/dist/commands/qa-run.js +4 -3
- package/dist/commands/review-pack.d.ts.map +1 -1
- package/dist/commands/review-pack.js +33 -6
- package/dist/core/agents/index.d.ts +1 -0
- package/dist/core/agents/index.d.ts.map +1 -1
- package/dist/core/agents/index.js +1 -0
- package/dist/core/agents/live-authority-v3.d.ts.map +1 -1
- package/dist/core/agents/live-authority-v3.js +11 -4
- package/dist/core/agents/render/session-context.d.ts +0 -6
- package/dist/core/agents/render/session-context.d.ts.map +1 -1
- package/dist/core/agents/render/session-context.js +1 -6
- package/dist/core/agents/session-events.d.ts.map +1 -1
- package/dist/core/agents/session-events.js +12 -4
- package/dist/core/agents/state/heartbeat-reader.d.ts +3 -0
- package/dist/core/agents/state/heartbeat-reader.d.ts.map +1 -1
- package/dist/core/agents/state/live-coordination-view.d.ts +3 -1
- package/dist/core/agents/state/live-coordination-view.d.ts.map +1 -1
- package/dist/core/agents/state/live-coordination-view.js +6 -2
- package/dist/core/agents/state/parent-reference-contract.d.ts +16 -0
- package/dist/core/agents/state/parent-reference-contract.d.ts.map +1 -0
- package/dist/core/agents/state/parent-reference-contract.js +1 -0
- package/dist/core/agents/state/parent-reference.d.ts +18 -0
- package/dist/core/agents/state/parent-reference.d.ts.map +1 -0
- package/dist/core/agents/state/parent-reference.js +119 -0
- package/dist/core/config.d.ts +39 -0
- package/dist/core/config.d.ts.map +1 -1
- package/dist/core/config.js +63 -0
- package/dist/core/diagnostics/path-identity.d.ts +1 -1
- package/dist/core/diagnostics/path-identity.d.ts.map +1 -1
- package/dist/core/diagnostics/path-identity.js +51 -6
- package/dist/core/events/v3/canonical.js +43 -14
- package/dist/core/events/v3/index.d.ts +1 -1
- package/dist/core/events/v3/index.d.ts.map +1 -1
- package/dist/core/events/v3/index.js +1 -1
- package/dist/core/events/v3/producers/recorder.d.ts +34 -0
- package/dist/core/events/v3/producers/recorder.d.ts.map +1 -1
- package/dist/core/events/v3/producers/recorder.js +117 -13
- package/dist/core/events/v3/reader.d.ts.map +1 -1
- package/dist/core/events/v3/reader.js +53 -13
- package/dist/core/events/v3/validate.d.ts.map +1 -1
- package/dist/core/events/v3/validate.js +36 -1
- package/dist/core/hooks/adapter/native-parent.d.ts +23 -0
- package/dist/core/hooks/adapter/native-parent.d.ts.map +1 -0
- package/dist/core/hooks/adapter/native-parent.js +91 -0
- package/dist/core/hooks/cli.js +79 -4
- package/dist/core/hooks/resolve/owner.d.ts +0 -11
- package/dist/core/hooks/resolve/owner.d.ts.map +1 -1
- package/dist/core/hooks/resolve/owner.js +0 -23
- package/dist/core/hooks/shell-admission.d.ts +84 -0
- package/dist/core/hooks/shell-admission.d.ts.map +1 -0
- package/dist/core/hooks/shell-admission.js +622 -0
- package/dist/core/hooks/shell-commit-tree.d.ts +2 -0
- package/dist/core/hooks/shell-commit-tree.d.ts.map +1 -0
- package/dist/core/hooks/shell-commit-tree.js +104 -0
- package/dist/core/inbox/contract.d.ts +12 -0
- package/dist/core/inbox/contract.d.ts.map +1 -1
- package/dist/core/inbox/contract.js +16 -0
- package/dist/core/inbox/peer-messages.d.ts +41 -16
- package/dist/core/inbox/peer-messages.d.ts.map +1 -1
- package/dist/core/inbox/peer-messages.js +372 -15
- package/dist/core/inbox/service.d.ts +8 -1
- package/dist/core/inbox/service.d.ts.map +1 -1
- package/dist/core/inbox/service.js +83 -3
- package/dist/core/inbox/targets.d.ts +17 -3
- package/dist/core/inbox/targets.d.ts.map +1 -1
- package/dist/core/inbox/targets.js +77 -2
- package/dist/core/presence/git.d.ts +18 -12
- package/dist/core/presence/git.d.ts.map +1 -1
- package/dist/core/presence/git.js +32 -38
- package/dist/core/presence/index.d.ts +2 -2
- package/dist/core/presence/index.d.ts.map +1 -1
- package/dist/core/presence/index.js +8 -6
- package/dist/core/presence/mail.d.ts +133 -0
- package/dist/core/presence/mail.d.ts.map +1 -0
- package/dist/core/presence/mail.js +464 -0
- package/dist/core/semantic/contract.d.ts +5 -5
- package/dist/core/storage/modes.d.ts +4 -0
- package/dist/core/storage/modes.d.ts.map +1 -1
- package/dist/core/storage/modes.js +4 -0
- package/dist/core/storage/segments.d.ts.map +1 -1
- package/dist/core/storage/segments.js +5 -4
- package/dist/lib/admission-history.d.ts +96 -0
- package/dist/lib/admission-history.d.ts.map +1 -0
- package/dist/lib/admission-history.js +196 -0
- package/dist/lib/admission.d.ts +56 -7
- package/dist/lib/admission.d.ts.map +1 -1
- package/dist/lib/admission.js +161 -19
- package/dist/lib/browser/client.d.ts +18 -0
- package/dist/lib/browser/client.d.ts.map +1 -1
- package/dist/lib/browser/client.js +100 -12
- package/dist/lib/browser/content-checks.d.ts +3 -1
- package/dist/lib/browser/content-checks.d.ts.map +1 -1
- package/dist/lib/browser/content-checks.js +10 -2
- package/dist/lib/browser/critique.d.ts +32 -0
- package/dist/lib/browser/critique.d.ts.map +1 -1
- package/dist/lib/browser/critique.js +72 -3
- package/dist/lib/browser/geometry.d.ts +2 -0
- package/dist/lib/browser/geometry.d.ts.map +1 -1
- package/dist/lib/browser/geometry.js +61 -15
- package/dist/lib/browser/index.d.ts +1 -1
- package/dist/lib/browser/index.d.ts.map +1 -1
- package/dist/lib/browser/index.js +1 -1
- package/dist/lib/browser/page-review-contracts.d.ts +6 -1
- package/dist/lib/browser/page-review-contracts.d.ts.map +1 -1
- package/dist/lib/browser/page-review-contracts.js +6 -1
- package/dist/lib/browser/page-review-judge.d.ts +3 -1
- package/dist/lib/browser/page-review-judge.d.ts.map +1 -1
- package/dist/lib/browser/page-review-judge.js +41 -11
- package/dist/lib/browser/page-review-pack.d.ts +3 -0
- package/dist/lib/browser/page-review-pack.d.ts.map +1 -1
- package/dist/lib/browser/page-review-pack.js +5 -2
- package/dist/lib/browser/qa-run-contracts.d.ts +11 -0
- package/dist/lib/browser/qa-run-contracts.d.ts.map +1 -1
- package/dist/lib/browser/qa-run-contracts.js +11 -4
- package/dist/lib/browser/qa-run.d.ts.map +1 -1
- package/dist/lib/browser/qa-run.js +73 -16
- package/dist/lib/browser/runts.d.ts +4 -2
- package/dist/lib/browser/runts.d.ts.map +1 -1
- package/dist/lib/browser/runts.js +84 -33
- package/dist/lib/browser/windows-chrome.d.ts +14 -0
- package/dist/lib/browser/windows-chrome.d.ts.map +1 -1
- package/dist/lib/browser/windows-chrome.js +42 -0
- package/dist/lib/browser/windows-login-sync.d.ts +110 -0
- package/dist/lib/browser/windows-login-sync.d.ts.map +1 -0
- package/dist/lib/browser/windows-login-sync.js +171 -0
- package/dist/lib/cookies/client.d.ts +30 -5
- package/dist/lib/cookies/client.d.ts.map +1 -1
- package/dist/lib/cookies/client.js +55 -10
- package/dist/lib/cookies/index.d.ts +1 -1
- package/dist/lib/cookies/index.d.ts.map +1 -1
- package/dist/lib/cookies/index.js +1 -1
- package/dist/lib/docs-metadata-sync.d.ts.map +1 -1
- package/dist/lib/docs-metadata-sync.js +41 -2
- package/dist/lib/durable-job.d.ts +8 -0
- package/dist/lib/durable-job.d.ts.map +1 -1
- package/dist/lib/durable-job.js +10 -0
- package/dist/lib/http/client.d.ts +9 -8
- package/dist/lib/http/client.d.ts.map +1 -1
- package/dist/lib/http/client.js +44 -2
- package/dist/lib/instructions/templates.js +4 -4
- package/package.json +2 -2
- package/src/commander.ts +13 -0
- package/src/commands/admission.ts +272 -29
- package/src/commands/agents.ts +132 -27
- package/src/commands/browse.ts +208 -6
- package/src/commands/fetch.ts +1 -0
- package/src/commands/ledger-v3.ts +8 -2
- package/src/commands/presence.ts +49 -0
- package/src/commands/qa-run.ts +4 -3
- package/src/commands/review-pack.ts +41 -5
- package/src/core/agents/index.ts +6 -0
- package/src/core/agents/live-authority-v3.ts +11 -4
- package/src/core/agents/render/session-context.ts +1 -7
- package/src/core/agents/session-events.ts +18 -3
- package/src/core/agents/state/heartbeat-reader.ts +3 -0
- package/src/core/agents/state/live-coordination-view.ts +13 -6
- package/src/core/agents/state/parent-reference-contract.ts +14 -0
- package/src/core/agents/state/parent-reference.ts +179 -0
- package/src/core/config.ts +85 -0
- package/src/core/diagnostics/path-identity.ts +52 -6
- package/src/core/events/v3/canonical.ts +46 -13
- package/src/core/events/v3/index.ts +3 -0
- package/src/core/events/v3/producers/recorder.ts +151 -13
- package/src/core/events/v3/reader.ts +55 -11
- package/src/core/events/v3/validate.ts +42 -1
- package/src/core/hooks/adapter/native-parent.ts +109 -0
- package/src/core/hooks/cli.ts +83 -4
- package/src/core/hooks/resolve/owner.ts +0 -23
- package/src/core/hooks/shell-admission.ts +634 -0
- package/src/core/hooks/shell-commit-tree.ts +102 -0
- package/src/core/inbox/contract.ts +18 -0
- package/src/core/inbox/peer-messages.ts +501 -15
- package/src/core/inbox/service.ts +108 -3
- package/src/core/inbox/targets.ts +94 -3
- package/src/core/presence/git.ts +45 -37
- package/src/core/presence/index.ts +16 -8
- package/src/core/presence/mail.ts +620 -0
- package/src/core/storage/modes.ts +6 -0
- package/src/core/storage/segments.ts +5 -4
- package/src/lib/admission-history.ts +267 -0
- package/src/lib/admission.ts +217 -19
- package/src/lib/browser/client.ts +147 -35
- package/src/lib/browser/content-checks.ts +14 -3
- package/src/lib/browser/critique.ts +113 -3
- package/src/lib/browser/geometry.ts +63 -14
- package/src/lib/browser/index.ts +5 -0
- package/src/lib/browser/page-review-contracts.ts +6 -1
- package/src/lib/browser/page-review-judge.ts +58 -13
- package/src/lib/browser/page-review-pack.ts +13 -2
- package/src/lib/browser/qa-run-contracts.ts +30 -4
- package/src/lib/browser/qa-run.ts +78 -17
- package/src/lib/browser/runts.ts +85 -37
- package/src/lib/browser/windows-chrome.ts +50 -0
- package/src/lib/browser/windows-login-sync.ts +275 -0
- package/src/lib/cookies/client.ts +62 -10
- package/src/lib/cookies/index.ts +3 -0
- package/src/lib/docs-metadata-sync.ts +44 -2
- package/src/lib/durable-job.ts +15 -0
- package/src/lib/http/client.ts +63 -1
- package/src/lib/instructions/templates.ts +4 -4
|
@@ -118,6 +118,33 @@ function addDays(value: string, days: number): string {
|
|
|
118
118
|
return date.toISOString().replace(".000Z", "Z");
|
|
119
119
|
}
|
|
120
120
|
|
|
121
|
+
/** Allowance for clock skew between machines before a timestamp counts as future. */
|
|
122
|
+
const FUTURE_SKEW_MS = 10 * 60 * 1000;
|
|
123
|
+
|
|
124
|
+
/** Lifecycle timestamps record events that already happened, so none may be later than now. */
|
|
125
|
+
const PAST_TIMESTAMP_FIELDS = [
|
|
126
|
+
"created_at",
|
|
127
|
+
"updated_at",
|
|
128
|
+
"status_changed_at",
|
|
129
|
+
"resolved_at",
|
|
130
|
+
"reviewed_at",
|
|
131
|
+
] as const;
|
|
132
|
+
|
|
133
|
+
function inFuture(value: unknown, now: string): boolean {
|
|
134
|
+
if (typeof value !== "string") return false;
|
|
135
|
+
const time = Date.parse(value);
|
|
136
|
+
return Number.isFinite(time) && time > Date.parse(now) + FUTURE_SKEW_MS;
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
/**
|
|
140
|
+
* While a status is unchanged its status_changed_at is pinned to the committed
|
|
141
|
+
* value. A committed value later than now cannot be true, so a correction to a
|
|
142
|
+
* time that has already passed is accepted instead of being reverted.
|
|
143
|
+
*/
|
|
144
|
+
function correctsFutureStatusTime(committed: unknown, current: unknown, now: string): boolean {
|
|
145
|
+
return inFuture(committed, now) && typeof current === "string" && !inFuture(current, now);
|
|
146
|
+
}
|
|
147
|
+
|
|
121
148
|
export async function runDocsMetadataSync(
|
|
122
149
|
opts: DocsMetadataSyncOpts,
|
|
123
150
|
): Promise<DocsMetadataSyncRow[]> {
|
|
@@ -171,7 +198,8 @@ export async function runDocsMetadataSync(
|
|
|
171
198
|
if (
|
|
172
199
|
!statusChanged &&
|
|
173
200
|
beforeV2 &&
|
|
174
|
-
current.data.status_changed_at !== beforeV2.status_changed_at
|
|
201
|
+
current.data.status_changed_at !== beforeV2.status_changed_at &&
|
|
202
|
+
!correctsFutureStatusTime(beforeV2.status_changed_at, current.data.status_changed_at, now)
|
|
175
203
|
) {
|
|
176
204
|
expected.status_changed_at = beforeV2.status_changed_at;
|
|
177
205
|
fields.push("status_changed_at");
|
|
@@ -203,6 +231,19 @@ export async function runDocsMetadataSync(
|
|
|
203
231
|
continue;
|
|
204
232
|
}
|
|
205
233
|
if (opts.check) {
|
|
234
|
+
const future = PAST_TIMESTAMP_FIELDS.filter((field) => inFuture(current.data[field], now));
|
|
235
|
+
if (future.length > 0) {
|
|
236
|
+
rows.push({
|
|
237
|
+
repo: target.name,
|
|
238
|
+
path,
|
|
239
|
+
status: "invalid",
|
|
240
|
+
fields: [...future],
|
|
241
|
+
message: future
|
|
242
|
+
.map((field) => `${field}: cannot be later than the current time`)
|
|
243
|
+
.join("; "),
|
|
244
|
+
});
|
|
245
|
+
continue;
|
|
246
|
+
}
|
|
206
247
|
const validation = validateDocsMetadataV2(current.data);
|
|
207
248
|
if (!validation.valid) {
|
|
208
249
|
rows.push({
|
|
@@ -238,7 +279,8 @@ export async function runDocsMetadataSync(
|
|
|
238
279
|
if (
|
|
239
280
|
beforeV2 &&
|
|
240
281
|
!statusChanged &&
|
|
241
|
-
current.data.status_changed_at !== beforeV2.status_changed_at
|
|
282
|
+
current.data.status_changed_at !== beforeV2.status_changed_at &&
|
|
283
|
+
!correctsFutureStatusTime(beforeV2.status_changed_at, current.data.status_changed_at, now)
|
|
242
284
|
) {
|
|
243
285
|
drift.push("status_changed_at");
|
|
244
286
|
}
|
package/src/lib/durable-job.ts
CHANGED
|
@@ -63,6 +63,11 @@ export interface DurableJobDocument {
|
|
|
63
63
|
/** Directory the wrapped command runs in. */
|
|
64
64
|
cwd: string;
|
|
65
65
|
created_at: string;
|
|
66
|
+
/**
|
|
67
|
+
* Wait while Linux memory pressure is above this before queueing, as the
|
|
68
|
+
* foreground run does. The client resolves it from the resource's project config at launch.
|
|
69
|
+
*/
|
|
70
|
+
defer_on_pressure?: { psi_full_avg10: number; max_wait_seconds: number };
|
|
66
71
|
}
|
|
67
72
|
|
|
68
73
|
export interface DurableJobStatus {
|
|
@@ -208,9 +213,19 @@ export function readJobDocument(jobDir: string): DurableJobDocument | null {
|
|
|
208
213
|
: [],
|
|
209
214
|
cwd: typeof parsed.cwd === "string" ? parsed.cwd : "",
|
|
210
215
|
created_at: typeof parsed.created_at === "string" ? parsed.created_at : "",
|
|
216
|
+
...readDeferOnPressure(parsed.defer_on_pressure),
|
|
211
217
|
};
|
|
212
218
|
}
|
|
213
219
|
|
|
220
|
+
function readDeferOnPressure(value: unknown): Pick<DurableJobDocument, "defer_on_pressure"> {
|
|
221
|
+
if (!isRecord(value)) return {};
|
|
222
|
+
const threshold = value.psi_full_avg10;
|
|
223
|
+
const maxWait = value.max_wait_seconds;
|
|
224
|
+
return typeof threshold === "number" && typeof maxWait === "number" && maxWait > 0
|
|
225
|
+
? { defer_on_pressure: { psi_full_avg10: threshold, max_wait_seconds: maxWait } }
|
|
226
|
+
: {};
|
|
227
|
+
}
|
|
228
|
+
|
|
214
229
|
/** Read the status document, or null when it is missing or unusable. */
|
|
215
230
|
export function readJobStatus(jobDir: string): DurableJobStatus | null {
|
|
216
231
|
const path = join(resolve(jobDir), DURABLE_JOB_STATUS_FILENAME);
|
package/src/lib/http/client.ts
CHANGED
|
@@ -2,7 +2,9 @@ import {
|
|
|
2
2
|
applyExtraCookies,
|
|
3
3
|
type Cookie,
|
|
4
4
|
type CookieJar,
|
|
5
|
+
domainMatches,
|
|
5
6
|
type ExtraCookies,
|
|
7
|
+
violatesCookiePrefix,
|
|
6
8
|
} from "../cookies/index.ts";
|
|
7
9
|
|
|
8
10
|
/**
|
|
@@ -52,6 +54,15 @@ export interface FetchOptions<TResponseType extends FetchResponseType = "text">
|
|
|
52
54
|
extraCookies?: ExtraCookies;
|
|
53
55
|
/** Response body representation. Default `text`; use `bytes` for lossless file output. */
|
|
54
56
|
responseType?: TResponseType;
|
|
57
|
+
/**
|
|
58
|
+
* With `redirect: "follow"`, follow redirects in this client instead of the
|
|
59
|
+
* runtime's fetch. Every hop then gets its own cookie header, `extraHeaders`
|
|
60
|
+
* call, and Set-Cookie persistence, so a caller that inspects those can stop
|
|
61
|
+
* a chain between hops. Credential headers are dropped on a cross-origin hop.
|
|
62
|
+
* Default: on whenever a `jar` is passed (host-only cookies must follow the
|
|
63
|
+
* jar's exact-host rule on every hop), off without one.
|
|
64
|
+
*/
|
|
65
|
+
clientRedirects?: boolean;
|
|
55
66
|
}
|
|
56
67
|
|
|
57
68
|
type FetchBody<TResponseType extends FetchResponseType> = TResponseType extends "bytes"
|
|
@@ -76,9 +87,55 @@ export interface FetchResult<TBody = string> {
|
|
|
76
87
|
* Streams aren't supported; this is a CLI helper, not a streaming HTTP
|
|
77
88
|
* client. Use Bun's `fetch` directly for streaming workloads.
|
|
78
89
|
*/
|
|
90
|
+
const REDIRECT_STATUSES = new Set([301, 302, 303, 307, 308]);
|
|
91
|
+
const MAX_CLIENT_REDIRECTS = 20;
|
|
92
|
+
|
|
79
93
|
export async function fetchWithJar<TResponseType extends FetchResponseType = "text">(
|
|
80
94
|
url: string,
|
|
81
95
|
opts: FetchOptions<TResponseType> = {},
|
|
96
|
+
): Promise<FetchResult<FetchBody<TResponseType>>> {
|
|
97
|
+
// With a jar, redirects are followed here so every hop gets its own Cookie
|
|
98
|
+
// header from the jar (exact-host for host-only cookies) and its own
|
|
99
|
+
// Set-Cookie persistence; the runtime would otherwise carry or drop the
|
|
100
|
+
// first hop's header on its own rules. Pass `clientRedirects: false` to opt out.
|
|
101
|
+
const clientRedirects = opts.clientRedirects ?? Boolean(opts.jar);
|
|
102
|
+
if (!clientRedirects || (opts.redirect ?? "follow") !== "follow") return fetchOnce(url, opts);
|
|
103
|
+
|
|
104
|
+
let current = url;
|
|
105
|
+
let method = opts.method ?? "GET";
|
|
106
|
+
let body = opts.body;
|
|
107
|
+
let headers = opts.headers;
|
|
108
|
+
let cookiesSaved = 0;
|
|
109
|
+
for (let hop = 0; ; hop++) {
|
|
110
|
+
const result = await fetchOnce(current, { ...opts, method, body, headers, redirect: "manual" });
|
|
111
|
+
cookiesSaved += result.cookiesSaved;
|
|
112
|
+
const location = result.headers.location;
|
|
113
|
+
if (!REDIRECT_STATUSES.has(result.status) || !location) return { ...result, cookiesSaved };
|
|
114
|
+
if (hop >= MAX_CLIENT_REDIRECTS) {
|
|
115
|
+
throw new Error(`Too many redirects (more than ${MAX_CLIENT_REDIRECTS}) starting at ${url}`);
|
|
116
|
+
}
|
|
117
|
+
const next = new URL(location, current);
|
|
118
|
+
if (
|
|
119
|
+
result.status === 303 ||
|
|
120
|
+
((result.status === 301 || result.status === 302) && method !== "GET" && method !== "HEAD")
|
|
121
|
+
) {
|
|
122
|
+
method = "GET";
|
|
123
|
+
body = undefined;
|
|
124
|
+
}
|
|
125
|
+
if (next.origin !== new URL(current).origin && headers) {
|
|
126
|
+
headers = Object.fromEntries(
|
|
127
|
+
Object.entries(headers).filter(
|
|
128
|
+
([name]) => !["authorization", "cookie"].includes(name.toLowerCase()),
|
|
129
|
+
),
|
|
130
|
+
);
|
|
131
|
+
}
|
|
132
|
+
current = next.href;
|
|
133
|
+
}
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
async function fetchOnce<TResponseType extends FetchResponseType = "text">(
|
|
137
|
+
url: string,
|
|
138
|
+
opts: FetchOptions<TResponseType> = {},
|
|
82
139
|
): Promise<FetchResult<FetchBody<TResponseType>>> {
|
|
83
140
|
const headers: Record<string, string> = { ...(opts.headers ?? {}) };
|
|
84
141
|
|
|
@@ -229,7 +286,9 @@ function parseSetCookie(raw: string, defaultDomain: string): Cookie | null {
|
|
|
229
286
|
for (const attr of parts.slice(1)) {
|
|
230
287
|
const lower = attr.toLowerCase();
|
|
231
288
|
if (lower.startsWith("domain=")) {
|
|
232
|
-
const d = attr.slice(7).trim();
|
|
289
|
+
const d = attr.slice(7).trim().toLowerCase();
|
|
290
|
+
// A server may only scope a cookie to its own host or a parent domain.
|
|
291
|
+
if (!d || !domainMatches(d, defaultDomain)) return null;
|
|
233
292
|
cookie.domain = d.startsWith(".") ? d : `.${d}`;
|
|
234
293
|
} else if (lower.startsWith("path=")) {
|
|
235
294
|
cookie.path = attr.slice(5).trim() || "/";
|
|
@@ -255,5 +314,8 @@ function parseSetCookie(raw: string, defaultDomain: string): Cookie | null {
|
|
|
255
314
|
}
|
|
256
315
|
}
|
|
257
316
|
|
|
317
|
+
// A cookie that breaks its name prefix is dropped, as a browser would.
|
|
318
|
+
if (violatesCookiePrefix(cookie)) return null;
|
|
319
|
+
|
|
258
320
|
return cookie;
|
|
259
321
|
}
|
|
@@ -133,10 +133,10 @@ carries a reason instead of \`(no intent)\`; the [tool-intent
|
|
|
133
133
|
guide](https://harnery.com/guides/tool-intent/) owns the details.
|
|
134
134
|
|
|
135
135
|
**Messaging another agent.** \`${b} agents ping <name> "<message>"\` reaches an
|
|
136
|
-
agent by name
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
136
|
+
agent by name, running or not, here or on another machine sharing this origin:
|
|
137
|
+
a live agent sees it on their next prompt (after a fetch, if remote), and a
|
|
138
|
+
dormant name holds it until that session next starts. Send it as your only step;
|
|
139
|
+
do not check who is live first or hunt elsewhere. Only an unused name is refused.
|
|
140
140
|
|
|
141
141
|
**Journal.** \`${b} journal add <category> "<text>"\` (category = ${journalCats})
|
|
142
142
|
leaves breadcrumbs that survive context compaction;
|