@indexnetwork/protocol 66.0.0-rc.632.1 → 66.0.0-rc.637.1
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.d.ts +2 -0
- package/dist/index.js +1 -0
- package/dist/internal/networks/network.pulse-summarizer.d.ts +41 -0
- package/dist/internal/networks/network.pulse-summarizer.js +113 -0
- package/dist/internal/opportunities/opportunity.cards.d.ts +5 -3
- package/dist/internal/opportunities/opportunity.cards.js +22 -6
- package/dist/internal/shared/agent/model.config.d.ts +6 -1
- package/dist/internal/shared/agent/model.config.js +1 -0
- package/dist/internal/shared/agent/model.resolver.d.ts +2 -1
- package/dist/internal/shared/agent/model.resolver.js +1 -0
- package/package.json +1 -1
package/dist/index.d.ts
CHANGED
|
@@ -27,6 +27,8 @@ export { decideNegotiationOpening, decideNegotiationTurn, observeNegotiation, ne
|
|
|
27
27
|
export type { NegotiationAction, NegotiationOutcome, NegotiationTurn, NegotiationState, NegotiationDecision, NegotiationRejection, NegotiationOpening, NegotiationOpeningDecision } from './protocol/negotiation.rules.js';
|
|
28
28
|
export type { NegotiationDatabase } from './platform/database/negotiation.js';
|
|
29
29
|
export { Networks } from "./capabilities/networks.js";
|
|
30
|
+
export { NetworkPulseSummarizer } from "./internal/networks/network.pulse-summarizer.js";
|
|
31
|
+
export type { NetworkPulseSummary, NetworkPulseSummaryInput } from "./internal/networks/network.pulse-summarizer.js";
|
|
30
32
|
export type { NetworksDeps } from "./capabilities/networks.js";
|
|
31
33
|
export { Intents } from "./capabilities/intents.js";
|
|
32
34
|
export type { PrepareAnswer, PrepareInput, PrepareResult, RecoveryField, RecoveryFieldKind, RecoveryFieldOption, IntentsDeps, IntentSemanticMetadata, PreparedIntent, } from "./capabilities/intents.js";
|
package/dist/index.js
CHANGED
|
@@ -31,6 +31,7 @@ export { decideNegotiationOpening, decideNegotiationTurn, observeNegotiation, ne
|
|
|
31
31
|
// The whole capability behind one class: the community lifecycle graph, the
|
|
32
32
|
// membership graph, and signal assignment.
|
|
33
33
|
export { Networks } from "./capabilities/networks.js";
|
|
34
|
+
export { NetworkPulseSummarizer } from "./internal/networks/network.pulse-summarizer.js";
|
|
34
35
|
// ─── Intents ──────────────────────────────────────────────────────────────────
|
|
35
36
|
// The whole capability behind one class: lifecycle graph, verification, and
|
|
36
37
|
// payload preparation.
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
import { z } from "zod";
|
|
2
|
+
export declare const NetworkPulseSummaryOutputSchema: z.ZodObject<{
|
|
3
|
+
summary: z.ZodString;
|
|
4
|
+
negotiations: z.ZodString;
|
|
5
|
+
}, "strip", z.ZodTypeAny, {
|
|
6
|
+
summary: string;
|
|
7
|
+
negotiations: string;
|
|
8
|
+
}, {
|
|
9
|
+
summary: string;
|
|
10
|
+
negotiations: string;
|
|
11
|
+
}>;
|
|
12
|
+
export type NetworkPulseSummaryOutput = z.infer<typeof NetworkPulseSummaryOutputSchema>;
|
|
13
|
+
export interface NetworkPulseSummaryInput {
|
|
14
|
+
networkTitle: string;
|
|
15
|
+
/** Recent open signals in the network, newest first, as members wrote them. */
|
|
16
|
+
signals: string[];
|
|
17
|
+
/** Recent negotiations: the two signals each pair of agents is weighing. */
|
|
18
|
+
negotiations?: Array<{
|
|
19
|
+
a: string;
|
|
20
|
+
b: string;
|
|
21
|
+
}>;
|
|
22
|
+
}
|
|
23
|
+
/** What the invite page shows of the room; either part may be absent. */
|
|
24
|
+
export interface NetworkPulseSummary {
|
|
25
|
+
summary: string | null;
|
|
26
|
+
negotiations: string | null;
|
|
27
|
+
}
|
|
28
|
+
/**
|
|
29
|
+
* Writes the anonymous "what people are looking for" overview for a network's
|
|
30
|
+
* public invite page. Follows the shared agent pattern: structured output,
|
|
31
|
+
* `invokeWithAbortSignal`, null on error.
|
|
32
|
+
*/
|
|
33
|
+
export declare class NetworkPulseSummarizer {
|
|
34
|
+
private model;
|
|
35
|
+
constructor();
|
|
36
|
+
/**
|
|
37
|
+
* @param input - The network's title, its recent open signals and negotiating pairs.
|
|
38
|
+
* @returns Both texts (each null when there is nothing suitable), or null when the call fails.
|
|
39
|
+
*/
|
|
40
|
+
invoke(input: NetworkPulseSummaryInput): Promise<NetworkPulseSummary | null>;
|
|
41
|
+
}
|
|
@@ -0,0 +1,113 @@
|
|
|
1
|
+
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
|
|
2
|
+
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
|
3
|
+
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
|
|
4
|
+
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
|
|
5
|
+
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
|
6
|
+
};
|
|
7
|
+
var __metadata = (this && this.__metadata) || function (k, v) {
|
|
8
|
+
if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
|
|
9
|
+
};
|
|
10
|
+
import { HumanMessage, SystemMessage } from "@langchain/core/messages";
|
|
11
|
+
import { z } from "zod";
|
|
12
|
+
import { log } from "../shared/observability/log.js";
|
|
13
|
+
import { Timed } from "../shared/observability/performance.js";
|
|
14
|
+
import { createStructuredModel } from "../shared/agent/model.config.js";
|
|
15
|
+
import { invokeWithAbortSignal } from "../shared/agent/model-signal.js";
|
|
16
|
+
// ─── Response schema ───────────────────────────────────────────────────────────
|
|
17
|
+
export const NetworkPulseSummaryOutputSchema = z.object({
|
|
18
|
+
summary: z
|
|
19
|
+
.string()
|
|
20
|
+
.describe("Two to four sentences, at most 70 words, on what members are after. Empty string when there is not enough suitable material."),
|
|
21
|
+
negotiations: z
|
|
22
|
+
.string()
|
|
23
|
+
.describe("One or two sentences, at most 45 words, on what the agents are negotiating about right now. Empty string when no pairs are given or none are suitable."),
|
|
24
|
+
});
|
|
25
|
+
// ─── Logger ───────────────────────────────────────────────────────────────────
|
|
26
|
+
const logger = log.lib.from("NetworkPulseSummarizer");
|
|
27
|
+
// ─── System prompt ────────────────────────────────────────────────────────────
|
|
28
|
+
const systemPrompt = `
|
|
29
|
+
You write the "what people are looking for" blurb on a network's public invite page.
|
|
30
|
+
Anyone holding the invite link reads it, including people who are not members.
|
|
31
|
+
|
|
32
|
+
TASK:
|
|
33
|
+
Read the members' open signals and write a short, clear overview, warm in tone, of what is
|
|
34
|
+
going on inside, so a visitor gets a feel for the room. Group signals into themes, e.g.
|
|
35
|
+
"A few people are looking for cofounders and early hires, others want to meet investors who
|
|
36
|
+
get crypto and AI, and at least one person just wants coffee before the conference."
|
|
37
|
+
|
|
38
|
+
PRIVACY (strict):
|
|
39
|
+
- Describe themes in aggregate. Never quote a signal or reuse its distinctive wording.
|
|
40
|
+
- No names of people, companies, products, projects, schools, or events.
|
|
41
|
+
- No places more specific than a broad region, no dates, numbers, amounts, links, or handles.
|
|
42
|
+
- Use loose quantities ("a few", "some", "several", "others"). Never "one person" for
|
|
43
|
+
anything specific enough to point at someone.
|
|
44
|
+
- Leave out entirely anything sexual or romantic, medical, legal, financial distress,
|
|
45
|
+
religious, political, illegal, hateful, or otherwise sensitive or crude. Do not hint at it.
|
|
46
|
+
|
|
47
|
+
STYLE:
|
|
48
|
+
- Two to four sentences, at most 70 words. Plain, friendly English.
|
|
49
|
+
- Mostly matter-of-fact: say clearly what kinds of people and asks are in the room. A light
|
|
50
|
+
touch of warmth is welcome in one phrase (the range of the room, an unexpected neighbour of
|
|
51
|
+
asks), but no punchlines and nothing at anyone's expense.
|
|
52
|
+
- No emoji, no exclamation marks, no em dashes, no headings or lists.
|
|
53
|
+
- Do not mention signals, agents, Index, or the network's name. Start with the content.
|
|
54
|
+
|
|
55
|
+
If fewer than three signals are suitable after the rules above, return an empty summary.
|
|
56
|
+
|
|
57
|
+
NEGOTIATIONS:
|
|
58
|
+
You may also get pairs of signals that two members' agents are negotiating over right now.
|
|
59
|
+
In "negotiations", say in one or two sentences, at most 45 words, what the agents are talking
|
|
60
|
+
about at a very high level: the kind of deal, never its details ("a few are working out
|
|
61
|
+
cofounder intros, others are trading notes on a speaking slot"). Same privacy rules, same
|
|
62
|
+
tone, at most one light touch of humor. Do not invent names for the agents. If no pairs are
|
|
63
|
+
given or none are suitable, return an empty string.
|
|
64
|
+
`;
|
|
65
|
+
// ─── Agent class ──────────────────────────────────────────────────────────────
|
|
66
|
+
/**
|
|
67
|
+
* Writes the anonymous "what people are looking for" overview for a network's
|
|
68
|
+
* public invite page. Follows the shared agent pattern: structured output,
|
|
69
|
+
* `invokeWithAbortSignal`, null on error.
|
|
70
|
+
*/
|
|
71
|
+
export class NetworkPulseSummarizer {
|
|
72
|
+
constructor() {
|
|
73
|
+
this.model = createStructuredModel("networkPulseSummarizer", NetworkPulseSummaryOutputSchema, {
|
|
74
|
+
name: "network_pulse_summary",
|
|
75
|
+
});
|
|
76
|
+
}
|
|
77
|
+
/**
|
|
78
|
+
* @param input - The network's title, its recent open signals and negotiating pairs.
|
|
79
|
+
* @returns Both texts (each null when there is nothing suitable), or null when the call fails.
|
|
80
|
+
*/
|
|
81
|
+
async invoke(input) {
|
|
82
|
+
const clean = (text) => text.replace(/\s+/g, " ").trim().slice(0, 400);
|
|
83
|
+
const signals = input.signals.map(clean).filter(Boolean);
|
|
84
|
+
const pairs = (input.negotiations ?? []).map((p) => ({ a: clean(p.a), b: clean(p.b) })).filter((p) => p.a && p.b);
|
|
85
|
+
if (signals.length < 3 && pairs.length < 2)
|
|
86
|
+
return { summary: null, negotiations: null };
|
|
87
|
+
const prompt = [
|
|
88
|
+
`## Network\n${input.networkTitle}`,
|
|
89
|
+
`## Open signals\n${signals.map((s) => `- ${s}`).join("\n") || "(none)"}`,
|
|
90
|
+
`## Negotiating pairs\n${pairs.map((p) => `- ${p.a} <-> ${p.b}`).join("\n") || "(none)"}`,
|
|
91
|
+
].join("\n\n");
|
|
92
|
+
try {
|
|
93
|
+
const result = await invokeWithAbortSignal(this.model, [new SystemMessage(systemPrompt), new HumanMessage(prompt)]);
|
|
94
|
+
const parsed = NetworkPulseSummaryOutputSchema.safeParse(result);
|
|
95
|
+
if (!parsed.success) {
|
|
96
|
+
logger.error("Schema validation failed", { error: parsed.error });
|
|
97
|
+
return null;
|
|
98
|
+
}
|
|
99
|
+
const tidy = (text) => text.replace(/\s+/g, " ").trim() || null;
|
|
100
|
+
return { summary: tidy(parsed.data.summary), negotiations: tidy(parsed.data.negotiations) };
|
|
101
|
+
}
|
|
102
|
+
catch (error) {
|
|
103
|
+
logger.error("Error during execution", { error });
|
|
104
|
+
return null;
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
__decorate([
|
|
109
|
+
Timed(),
|
|
110
|
+
__metadata("design:type", Function),
|
|
111
|
+
__metadata("design:paramtypes", [Object]),
|
|
112
|
+
__metadata("design:returntype", Promise)
|
|
113
|
+
], NetworkPulseSummarizer.prototype, "invoke", null);
|
|
@@ -60,9 +60,11 @@ export declare function presentOpportunityCard(deps: OpportunityCardsDeps, oppor
|
|
|
60
60
|
}): Promise<OpportunityCard | null>;
|
|
61
61
|
/**
|
|
62
62
|
* List the viewer's opportunities in the given statuses as presented cards,
|
|
63
|
-
*
|
|
64
|
-
*
|
|
65
|
-
*
|
|
63
|
+
* one card per counterpart. An accepted row keeps that person's slot over a
|
|
64
|
+
* newer pending or negotiating one, and a pending row this viewer already
|
|
65
|
+
* committed to keeps it over a newer unanswered one. Among the same rank,
|
|
66
|
+
* newest wins. A rejected or expired row never takes the slot from a live
|
|
67
|
+
* one. Cards whose presentation fails are dropped.
|
|
66
68
|
*
|
|
67
69
|
* @param deps - Database, cache, and presenter.
|
|
68
70
|
* @param input - Viewer, statuses, optional network/intent scope, limit, cache bypass, skeleton mode.
|
|
@@ -33,6 +33,20 @@ function counterpartUserIds(opportunity, viewerId) {
|
|
|
33
33
|
function viewerHasCommitted(opportunity, viewerId) {
|
|
34
34
|
return (opportunity.committedActorIds ?? []).includes(viewerId);
|
|
35
35
|
}
|
|
36
|
+
/**
|
|
37
|
+
* Which row keeps a person's single radar slot.
|
|
38
|
+
* Accepted first, then a pending row this viewer already committed to,
|
|
39
|
+
* then other live rows. Rejected and expired never take the slot from those.
|
|
40
|
+
*/
|
|
41
|
+
function counterpartSlotRank(opportunity, viewerId) {
|
|
42
|
+
if (opportunity.status === 'rejected' || opportunity.status === 'expired')
|
|
43
|
+
return 3;
|
|
44
|
+
if (opportunity.status === 'accepted')
|
|
45
|
+
return 0;
|
|
46
|
+
if (opportunity.status === 'pending' && viewerHasCommitted(opportunity, viewerId))
|
|
47
|
+
return 1;
|
|
48
|
+
return 2;
|
|
49
|
+
}
|
|
36
50
|
function stampViewerCommitted(card, viewerCommitted) {
|
|
37
51
|
return { ...card, viewerCommitted };
|
|
38
52
|
}
|
|
@@ -113,9 +127,11 @@ export async function presentOpportunityCard(deps, opportunity, viewerId, option
|
|
|
113
127
|
}
|
|
114
128
|
/**
|
|
115
129
|
* List the viewer's opportunities in the given statuses as presented cards,
|
|
116
|
-
*
|
|
117
|
-
*
|
|
118
|
-
*
|
|
130
|
+
* one card per counterpart. An accepted row keeps that person's slot over a
|
|
131
|
+
* newer pending or negotiating one, and a pending row this viewer already
|
|
132
|
+
* committed to keeps it over a newer unanswered one. Among the same rank,
|
|
133
|
+
* newest wins. A rejected or expired row never takes the slot from a live
|
|
134
|
+
* one. Cards whose presentation fails are dropped.
|
|
119
135
|
*
|
|
120
136
|
* @param deps - Database, cache, and presenter.
|
|
121
137
|
* @param input - Viewer, statuses, optional network/intent scope, limit, cache bypass, skeleton mode.
|
|
@@ -133,9 +149,9 @@ export async function listOpportunityCards(deps, input) {
|
|
|
133
149
|
const visible = raw
|
|
134
150
|
.filter((opp) => requested.has(opp.status) && canUserSeeOpportunity(opp.actors, opp.status, viewerId))
|
|
135
151
|
.sort((a, b) => {
|
|
136
|
-
const
|
|
137
|
-
if (
|
|
138
|
-
return
|
|
152
|
+
const rank = counterpartSlotRank(a, viewerId) - counterpartSlotRank(b, viewerId);
|
|
153
|
+
if (rank !== 0)
|
|
154
|
+
return rank;
|
|
139
155
|
return b.createdAt.getTime() - a.createdAt.getTime();
|
|
140
156
|
});
|
|
141
157
|
const seen = new Set();
|
|
@@ -32,7 +32,7 @@ export interface ModelConfig {
|
|
|
32
32
|
chatReasoningEffort?: 'low' | 'medium' | 'high';
|
|
33
33
|
}
|
|
34
34
|
/** Per-agent model settings before canonical assignments are applied. */
|
|
35
|
-
declare function getBaseModelConfig(config?: ModelConfig): { [Agent in "intentInferrer" | "intentVerifier" | "intentClarifier" | "profileGenerator" | "opportunityPresenter" | "negotiator" | "negotiationReflector" | "homeCategorizer" | "suggestionGenerator" | "chatTitleGenerator" | "negotiationInsights" | "chatContextSummarizer" | "negotiationSummarizer" | "inviteGenerator" | "userContextGenerator" | "networkRecommender" | "interruptClassifier" | "chat"]: Omit<{
|
|
35
|
+
declare function getBaseModelConfig(config?: ModelConfig): { [Agent in "intentInferrer" | "intentVerifier" | "intentClarifier" | "profileGenerator" | "opportunityPresenter" | "negotiator" | "negotiationReflector" | "homeCategorizer" | "suggestionGenerator" | "chatTitleGenerator" | "negotiationInsights" | "chatContextSummarizer" | "negotiationSummarizer" | "inviteGenerator" | "userContextGenerator" | "networkRecommender" | "networkPulseSummarizer" | "interruptClassifier" | "chat"]: Omit<{
|
|
36
36
|
readonly intentInferrer: {
|
|
37
37
|
readonly model: "google/gemini-3.7-flash";
|
|
38
38
|
};
|
|
@@ -99,6 +99,11 @@ declare function getBaseModelConfig(config?: ModelConfig): { [Agent in "intentIn
|
|
|
99
99
|
readonly temperature: 0.2;
|
|
100
100
|
readonly maxTokens: 512;
|
|
101
101
|
};
|
|
102
|
+
readonly networkPulseSummarizer: {
|
|
103
|
+
readonly model: "google/gemini-3.7-flash";
|
|
104
|
+
readonly temperature: 0.7;
|
|
105
|
+
readonly maxTokens: 400;
|
|
106
|
+
};
|
|
102
107
|
readonly interruptClassifier: {
|
|
103
108
|
readonly model: "google/gemini-3.7-flash";
|
|
104
109
|
readonly temperature: 0;
|
|
@@ -20,6 +20,7 @@ function getBaseModelConfig(config) {
|
|
|
20
20
|
inviteGenerator: { model: "google/gemini-3.7-flash", temperature: 0.3, maxTokens: 512 },
|
|
21
21
|
userContextGenerator: { model: "google/gemini-3.7-flash", temperature: 0.3, maxTokens: 512 },
|
|
22
22
|
networkRecommender: { model: "google/gemini-3.7-flash", temperature: 0.2, maxTokens: 512 },
|
|
23
|
+
networkPulseSummarizer: { model: "google/gemini-3.7-flash", temperature: 0.7, maxTokens: 400 },
|
|
23
24
|
interruptClassifier: { model: "google/gemini-3.7-flash", temperature: 0.0, maxTokens: 16 },
|
|
24
25
|
chat: {
|
|
25
26
|
model: "google/gemini-3.7-flash",
|
|
@@ -22,12 +22,13 @@ export declare const CANONICAL_AGENT_MODEL_DEFAULTS: Readonly<{
|
|
|
22
22
|
readonly inviteGenerator: "google/gemini-3.7-flash";
|
|
23
23
|
readonly userContextGenerator: "google/gemini-3.7-flash";
|
|
24
24
|
readonly networkRecommender: "google/gemini-3.7-flash";
|
|
25
|
+
readonly networkPulseSummarizer: "google/gemini-3.7-flash";
|
|
25
26
|
readonly interruptClassifier: "google/gemini-3.7-flash";
|
|
26
27
|
readonly chat: "google/gemini-3.7-flash";
|
|
27
28
|
}>;
|
|
28
29
|
export type CanonicalModelAgent = keyof typeof CANONICAL_AGENT_MODEL_DEFAULTS;
|
|
29
30
|
export type CanonicalAllAgentModels = Readonly<Record<CanonicalModelAgent, string>>;
|
|
30
|
-
export declare const CANONICAL_MODEL_AGENTS: readonly ("intentInferrer" | "intentVerifier" | "intentClarifier" | "profileGenerator" | "opportunityPresenter" | "negotiator" | "negotiationReflector" | "homeCategorizer" | "suggestionGenerator" | "chatTitleGenerator" | "negotiationInsights" | "chatContextSummarizer" | "negotiationSummarizer" | "inviteGenerator" | "userContextGenerator" | "networkRecommender" | "interruptClassifier" | "chat")[];
|
|
31
|
+
export declare const CANONICAL_MODEL_AGENTS: readonly ("intentInferrer" | "intentVerifier" | "intentClarifier" | "profileGenerator" | "opportunityPresenter" | "negotiator" | "negotiationReflector" | "homeCategorizer" | "suggestionGenerator" | "chatTitleGenerator" | "negotiationInsights" | "chatContextSummarizer" | "negotiationSummarizer" | "inviteGenerator" | "userContextGenerator" | "networkRecommender" | "networkPulseSummarizer" | "interruptClassifier" | "chat")[];
|
|
31
32
|
export declare function resolveCanonicalAllAgentModels(environment: Readonly<Record<string, string | undefined>>, options?: {
|
|
32
33
|
applyEvalOverrides?: boolean;
|
|
33
34
|
}): CanonicalAllAgentModels;
|
|
@@ -22,6 +22,7 @@ export const CANONICAL_AGENT_MODEL_DEFAULTS = Object.freeze({
|
|
|
22
22
|
inviteGenerator: "google/gemini-3.7-flash",
|
|
23
23
|
userContextGenerator: "google/gemini-3.7-flash",
|
|
24
24
|
networkRecommender: "google/gemini-3.7-flash",
|
|
25
|
+
networkPulseSummarizer: "google/gemini-3.7-flash",
|
|
25
26
|
interruptClassifier: "google/gemini-3.7-flash",
|
|
26
27
|
chat: "google/gemini-3.7-flash",
|
|
27
28
|
});
|