@indexnetwork/protocol 66.0.0-rc.643.1 → 66.0.0-rc.646.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
CHANGED
|
@@ -32,6 +32,8 @@ export type { NetworkPulseSummary, NetworkPulseSummaryInput } from "./internal/n
|
|
|
32
32
|
export type { NetworksDeps } from "./capabilities/networks.js";
|
|
33
33
|
export { Intents } from "./capabilities/intents.js";
|
|
34
34
|
export type { PrepareAnswer, PrepareInput, PrepareResult, RecoveryField, RecoveryFieldKind, RecoveryFieldOption, IntentsDeps, IntentSemanticMetadata, PreparedIntent, } from "./capabilities/intents.js";
|
|
35
|
+
export { IntentSuggester } from "./internal/intents/intent.suggester.js";
|
|
36
|
+
export type { IntentSuggestion, IntentSuggestionInput, IntentSuggestions } from "./internal/intents/intent.suggester.js";
|
|
35
37
|
export { normalizeTelegramHandle } from './internal/shared/utils/telegram-handle.js';
|
|
36
38
|
/**
|
|
37
39
|
* opportunity — the capability's sole cross-capability surface.
|
package/dist/index.js
CHANGED
|
@@ -36,6 +36,7 @@ export { NetworkPulseSummarizer } from "./internal/networks/network.pulse-summar
|
|
|
36
36
|
// The whole capability behind one class: lifecycle graph, verification, and
|
|
37
37
|
// payload preparation.
|
|
38
38
|
export { Intents } from "./capabilities/intents.js";
|
|
39
|
+
export { IntentSuggester } from "./internal/intents/intent.suggester.js";
|
|
39
40
|
// ─── Agents ───────────────────────────────────────────────────────────────────
|
|
40
41
|
export { normalizeTelegramHandle } from './internal/shared/utils/telegram-handle.js';
|
|
41
42
|
// ─── Opportunity compatibility exports ─────────────────────────────────────
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
import { z } from "zod";
|
|
2
|
+
export declare const IntentSuggestionOutputSchema: z.ZodObject<{
|
|
3
|
+
lookingFor: z.ZodArray<z.ZodString, "many">;
|
|
4
|
+
offering: z.ZodString;
|
|
5
|
+
examples: z.ZodArray<z.ZodString, "many">;
|
|
6
|
+
}, "strip", z.ZodTypeAny, {
|
|
7
|
+
lookingFor: string[];
|
|
8
|
+
offering: string;
|
|
9
|
+
examples: string[];
|
|
10
|
+
}, {
|
|
11
|
+
lookingFor: string[];
|
|
12
|
+
offering: string;
|
|
13
|
+
examples: string[];
|
|
14
|
+
}>;
|
|
15
|
+
export interface IntentSuggestionInput {
|
|
16
|
+
name: string | null;
|
|
17
|
+
intro: string | null;
|
|
18
|
+
location: string | null;
|
|
19
|
+
/** The person's active intents, so no suggestion repeats one. */
|
|
20
|
+
existingIntents: string[];
|
|
21
|
+
}
|
|
22
|
+
/** One suggested first intent; `kind` says which side of a match it is on. */
|
|
23
|
+
export interface IntentSuggestion {
|
|
24
|
+
kind: "looking_for" | "offering";
|
|
25
|
+
text: string;
|
|
26
|
+
}
|
|
27
|
+
/** The picks, plus the example starters rewritten for this person. */
|
|
28
|
+
export interface IntentSuggestions {
|
|
29
|
+
suggestions: IntentSuggestion[];
|
|
30
|
+
examples: string[];
|
|
31
|
+
}
|
|
32
|
+
/**
|
|
33
|
+
* Suggests a new member's first intents from their profile: two they might be
|
|
34
|
+
* looking for and one they could offer. Follows the shared agent pattern:
|
|
35
|
+
* structured output, `invokeWithAbortSignal`, null on error.
|
|
36
|
+
*/
|
|
37
|
+
export declare class IntentSuggester {
|
|
38
|
+
private model;
|
|
39
|
+
constructor();
|
|
40
|
+
/**
|
|
41
|
+
* @param input - The person's profile and their active intents.
|
|
42
|
+
* @returns Two "looking_for" suggestions then one "offering", with the rewritten examples; null when the call fails.
|
|
43
|
+
*/
|
|
44
|
+
invoke(input: IntentSuggestionInput): Promise<IntentSuggestions | null>;
|
|
45
|
+
}
|
|
@@ -0,0 +1,127 @@
|
|
|
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
|
+
const SuggestionText = z
|
|
18
|
+
.string()
|
|
19
|
+
.describe("One line, at most 90 characters, in the person's own voice, lowercase, no trailing period.");
|
|
20
|
+
export const IntentSuggestionOutputSchema = z.object({
|
|
21
|
+
lookingFor: z
|
|
22
|
+
.array(SuggestionText)
|
|
23
|
+
.describe("Exactly two things they might want: someone to learn from, hire, fund, build with, or meet."),
|
|
24
|
+
offering: SuggestionText.describe("One thing they could offer others: their skills, capital, time, or help."),
|
|
25
|
+
examples: z
|
|
26
|
+
.array(z.string().describe("One line, at most 110 characters, lowercase, no trailing period."))
|
|
27
|
+
.describe("Five to seven of the example starters, rewritten for this person in the same casual shape."),
|
|
28
|
+
});
|
|
29
|
+
// ─── Logger ───────────────────────────────────────────────────────────────────
|
|
30
|
+
const logger = log.lib.from("IntentSuggester");
|
|
31
|
+
// ─── System prompt ────────────────────────────────────────────────────────────
|
|
32
|
+
const systemPrompt = `
|
|
33
|
+
You are someone's agent on Index, a network where an agent finds the right people for its
|
|
34
|
+
person by matching intents: what they are looking for and what they can offer.
|
|
35
|
+
|
|
36
|
+
TASK:
|
|
37
|
+
They just joined. From their profile, suggest three intents they could start with:
|
|
38
|
+
- two things they might be looking for (someone to learn from, hire, fund, build with, or meet)
|
|
39
|
+
- one thing they could offer (their skills, capital, time, or help)
|
|
40
|
+
|
|
41
|
+
RULES:
|
|
42
|
+
- Write each in their voice, first person implied, like they would type it:
|
|
43
|
+
"looking for a technical cofounder who has shipped ml in production",
|
|
44
|
+
"happy to give early founders feedback on their go-to-market".
|
|
45
|
+
- Ground every suggestion in the profile: their role and field. What we found may be old, so
|
|
46
|
+
stay at that level: never name a company, product, fund, school, or city, and leave out
|
|
47
|
+
details that go stale (stage, round, team size, dates). Do not invent facts.
|
|
48
|
+
- One line each, at most 90 characters, lowercase, no trailing period, no emoji, no em dashes.
|
|
49
|
+
- Skip anything that repeats one of their existing intents.
|
|
50
|
+
- If the profile says little, still give three plausible, specific starting points.
|
|
51
|
+
|
|
52
|
+
EXAMPLES:
|
|
53
|
+
Also rewrite these generic starters for this person, keeping their short, casual
|
|
54
|
+
"situation, want ..." shape:
|
|
55
|
+
- traveling soon, want to meet cool people in ai
|
|
56
|
+
- building something, want honest feedback on it
|
|
57
|
+
- just launched, want cool people to try it
|
|
58
|
+
- new in town, want to find my people
|
|
59
|
+
- raising soon, want to meet investors who get it
|
|
60
|
+
- hiring soon, want to meet great people early
|
|
61
|
+
- have an idea, want someone to build it with
|
|
62
|
+
Give each a light touch so it feels like theirs: swap the generic part for their broad field or
|
|
63
|
+
role, nothing more. A founder in agent infrastructure might get "traveling soon, want to meet people
|
|
64
|
+
building or investing in agents". Same limits as above: no company, product, fund, school, or city
|
|
65
|
+
names, and nothing that would go stale. Keep them short and loose; one field word is usually enough.
|
|
66
|
+
Swap any that do not fit their role for one that does: an investor does not raise, so "raising soon"
|
|
67
|
+
becomes something like "deploying capital, want to meet founders in <their broad focus>"; someone who
|
|
68
|
+
is not building does not launch. Drop any you cannot make fit, but always keep the traveling one.
|
|
69
|
+
Return five to seven, each at most 90 characters, lowercase, no trailing period, no emoji, no em
|
|
70
|
+
dashes, and none that repeat the three suggestions above.
|
|
71
|
+
`;
|
|
72
|
+
// ─── Agent class ──────────────────────────────────────────────────────────────
|
|
73
|
+
/**
|
|
74
|
+
* Suggests a new member's first intents from their profile: two they might be
|
|
75
|
+
* looking for and one they could offer. Follows the shared agent pattern:
|
|
76
|
+
* structured output, `invokeWithAbortSignal`, null on error.
|
|
77
|
+
*/
|
|
78
|
+
export class IntentSuggester {
|
|
79
|
+
constructor() {
|
|
80
|
+
this.model = createStructuredModel("suggestionGenerator", IntentSuggestionOutputSchema, {
|
|
81
|
+
name: "intent_suggestions",
|
|
82
|
+
});
|
|
83
|
+
}
|
|
84
|
+
/**
|
|
85
|
+
* @param input - The person's profile and their active intents.
|
|
86
|
+
* @returns Two "looking_for" suggestions then one "offering", with the rewritten examples; null when the call fails.
|
|
87
|
+
*/
|
|
88
|
+
async invoke(input) {
|
|
89
|
+
const clean = (text, max) => (text ?? "").replace(/\s+/g, " ").trim().slice(0, max);
|
|
90
|
+
const prompt = [
|
|
91
|
+
`## Name\n${clean(input.name, 200) || "(unknown)"}`,
|
|
92
|
+
`## Location\n${clean(input.location, 200) || "(unknown)"}`,
|
|
93
|
+
`## Intro\n${clean(input.intro, 4000) || "(empty)"}`,
|
|
94
|
+
`## Existing intents\n${input.existingIntents.map((s) => `- ${clean(s, 400)}`).join("\n") || "(none)"}`,
|
|
95
|
+
].join("\n\n");
|
|
96
|
+
try {
|
|
97
|
+
const result = await invokeWithAbortSignal(this.model, [new SystemMessage(systemPrompt), new HumanMessage(prompt)]);
|
|
98
|
+
const parsed = IntentSuggestionOutputSchema.safeParse(result);
|
|
99
|
+
if (!parsed.success) {
|
|
100
|
+
logger.error("Schema validation failed", { error: parsed.error });
|
|
101
|
+
return null;
|
|
102
|
+
}
|
|
103
|
+
const tidy = (text) => text.replace(/\s+/g, " ").trim().replace(/\.$/, "");
|
|
104
|
+
const lookingFor = parsed.data.lookingFor.map(tidy).filter(Boolean).slice(0, 2);
|
|
105
|
+
const offering = tidy(parsed.data.offering);
|
|
106
|
+
if (lookingFor.length < 2 || !offering)
|
|
107
|
+
return null;
|
|
108
|
+
return {
|
|
109
|
+
suggestions: [
|
|
110
|
+
...lookingFor.map((text) => ({ kind: "looking_for", text })),
|
|
111
|
+
{ kind: "offering", text: offering },
|
|
112
|
+
],
|
|
113
|
+
examples: parsed.data.examples.map(tidy).filter((text) => text && text.length <= 140).slice(0, 7),
|
|
114
|
+
};
|
|
115
|
+
}
|
|
116
|
+
catch (error) {
|
|
117
|
+
logger.error("Error during execution", { error });
|
|
118
|
+
return null;
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
__decorate([
|
|
123
|
+
Timed(),
|
|
124
|
+
__metadata("design:type", Function),
|
|
125
|
+
__metadata("design:paramtypes", [Object]),
|
|
126
|
+
__metadata("design:returntype", Promise)
|
|
127
|
+
], IntentSuggester.prototype, "invoke", null);
|